[sgen] One internal allocator per worker thread, to get rid of locking.
[mono-project/dkf.git] / mono / metadata / reflection.c
blob450c57270de545b5538a39400db1553edc519b81
1 /*
2 * reflection.c: Routines for creating an image at runtime.
3 *
4 * Author:
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 #include <config.h>
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
28 #include <stdio.h>
29 #include <glib.h>
30 #include <errno.h>
31 #include <time.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include "image.h"
35 #include "cil-coff.h"
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
40 #include <mono/metadata/debug-helpers.h>
41 #include <mono/metadata/verify-internals.h>
42 #include <mono/metadata/mono-ptr-array.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
47 #if HAVE_SGEN_GC
48 static void* reflection_info_desc = NULL;
49 #define MOVING_GC_REGISTER(addr) do { \
50 if (!reflection_info_desc) { \
51 gsize bmap = 1; \
52 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
53 } \
54 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
55 } while (0)
56 #else
57 #define MOVING_GC_REGISTER(addr)
58 #endif
60 static gboolean is_usertype (MonoReflectionType *ref);
61 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
63 typedef struct {
64 char *p;
65 char *buf;
66 char *end;
67 } SigBuffer;
69 #define TEXT_OFFSET 512
70 #define CLI_H_SIZE 136
71 #define FILE_ALIGN 512
72 #define VIRT_ALIGN 8192
73 #define START_TEXT_RVA 0x00002000
75 typedef struct {
76 MonoReflectionILGen *ilgen;
77 MonoReflectionType *rtype;
78 MonoArray *parameters;
79 MonoArray *generic_params;
80 MonoGenericContainer *generic_container;
81 MonoArray *pinfo;
82 MonoArray *opt_types;
83 guint32 attrs;
84 guint32 iattrs;
85 guint32 call_conv;
86 guint32 *table_idx; /* note: it's a pointer */
87 MonoArray *code;
88 MonoObject *type;
89 MonoString *name;
90 MonoBoolean init_locals;
91 MonoBoolean skip_visibility;
92 MonoArray *return_modreq;
93 MonoArray *return_modopt;
94 MonoArray *param_modreq;
95 MonoArray *param_modopt;
96 MonoArray *permissions;
97 MonoMethod *mhandle;
98 guint32 nrefs;
99 gpointer *refs;
100 /* for PInvoke */
101 int charset, extra_flags, native_cc;
102 MonoString *dll, *dllentry;
103 } ReflectionMethodBuilder;
105 typedef struct {
106 guint32 owner;
107 MonoReflectionGenericParam *gparam;
108 } GenericParamTableEntry;
110 const unsigned char table_sizes [MONO_TABLE_NUM] = {
111 MONO_MODULE_SIZE,
112 MONO_TYPEREF_SIZE,
113 MONO_TYPEDEF_SIZE,
115 MONO_FIELD_SIZE,
117 MONO_METHOD_SIZE,
119 MONO_PARAM_SIZE,
120 MONO_INTERFACEIMPL_SIZE,
121 MONO_MEMBERREF_SIZE, /* 0x0A */
122 MONO_CONSTANT_SIZE,
123 MONO_CUSTOM_ATTR_SIZE,
124 MONO_FIELD_MARSHAL_SIZE,
125 MONO_DECL_SECURITY_SIZE,
126 MONO_CLASS_LAYOUT_SIZE,
127 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
128 MONO_STAND_ALONE_SIGNATURE_SIZE,
129 MONO_EVENT_MAP_SIZE,
131 MONO_EVENT_SIZE,
132 MONO_PROPERTY_MAP_SIZE,
134 MONO_PROPERTY_SIZE,
135 MONO_METHOD_SEMA_SIZE,
136 MONO_METHODIMPL_SIZE,
137 MONO_MODULEREF_SIZE, /* 0x1A */
138 MONO_TYPESPEC_SIZE,
139 MONO_IMPLMAP_SIZE,
140 MONO_FIELD_RVA_SIZE,
143 MONO_ASSEMBLY_SIZE, /* 0x20 */
144 MONO_ASSEMBLY_PROCESSOR_SIZE,
145 MONO_ASSEMBLYOS_SIZE,
146 MONO_ASSEMBLYREF_SIZE,
147 MONO_ASSEMBLYREFPROC_SIZE,
148 MONO_ASSEMBLYREFOS_SIZE,
149 MONO_FILE_SIZE,
150 MONO_EXP_TYPE_SIZE,
151 MONO_MANIFEST_SIZE,
152 MONO_NESTED_CLASS_SIZE,
154 MONO_GENERICPARAM_SIZE, /* 0x2A */
155 MONO_METHODSPEC_SIZE,
156 MONO_GENPARCONSTRAINT_SIZE
160 #ifndef DISABLE_REFLECTION_EMIT
161 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
162 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
163 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
164 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
165 static void ensure_runtime_vtable (MonoClass *klass);
166 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
167 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
168 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
169 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
170 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
171 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
172 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
173 #endif
175 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
176 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
177 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
178 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
179 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
180 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
181 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
182 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
183 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
184 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
185 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
186 static gboolean is_sre_array (MonoClass *class);
187 static gboolean is_sre_byref (MonoClass *class);
188 static gboolean is_sre_pointer (MonoClass *class);
189 static gboolean is_sre_type_builder (MonoClass *class);
190 static gboolean is_sre_method_builder (MonoClass *class);
191 static gboolean is_sre_ctor_builder (MonoClass *class);
192 static gboolean is_sre_field_builder (MonoClass *class);
193 static gboolean is_sr_mono_method (MonoClass *class);
194 static gboolean is_sr_mono_cmethod (MonoClass *class);
195 static gboolean is_sr_mono_generic_method (MonoClass *class);
196 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
197 static gboolean is_sr_mono_field (MonoClass *class);
198 static gboolean is_sr_mono_property (MonoClass *class);
199 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
200 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
202 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
203 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
204 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
206 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
207 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
208 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
209 __type = mono_reflection_type_resolve_user_types (__type); \
210 mono_array_set (arr, MonoReflectionType*, index, __type); \
211 } while (0)
213 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
215 void
216 mono_reflection_init (void)
220 static void
221 sigbuffer_init (SigBuffer *buf, int size)
223 buf->buf = g_malloc (size);
224 buf->p = buf->buf;
225 buf->end = buf->buf + size;
228 static void
229 sigbuffer_make_room (SigBuffer *buf, int size)
231 if (buf->end - buf->p < size) {
232 int new_size = buf->end - buf->buf + size + 32;
233 char *p = g_realloc (buf->buf, new_size);
234 size = buf->p - buf->buf;
235 buf->buf = p;
236 buf->p = p + size;
237 buf->end = buf->buf + new_size;
241 static void
242 sigbuffer_add_value (SigBuffer *buf, guint32 val)
244 sigbuffer_make_room (buf, 6);
245 mono_metadata_encode_value (val, buf->p, &buf->p);
248 static void
249 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
251 sigbuffer_make_room (buf, 1);
252 buf->p [0] = val;
253 buf->p++;
256 static void
257 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
259 sigbuffer_make_room (buf, size);
260 memcpy (buf->p, p, size);
261 buf->p += size;
264 static void
265 sigbuffer_free (SigBuffer *buf)
267 g_free (buf->buf);
270 #ifndef DISABLE_REFLECTION_EMIT
272 * mp_g_alloc:
274 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
275 * from the C heap.
277 static gpointer
278 image_g_malloc (MonoImage *image, guint size)
280 if (image)
281 return mono_image_alloc (image, size);
282 else
283 return g_malloc (size);
285 #endif /* !DISABLE_REFLECTION_EMIT */
288 * image_g_alloc0:
290 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
291 * from the C heap.
293 static gpointer
294 image_g_malloc0 (MonoImage *image, guint size)
296 if (image)
297 return mono_image_alloc0 (image, size);
298 else
299 return g_malloc0 (size);
302 #ifndef DISABLE_REFLECTION_EMIT
303 static char*
304 image_strdup (MonoImage *image, const char *s)
306 if (image)
307 return mono_image_strdup (image, s);
308 else
309 return g_strdup (s);
311 #endif
313 #define image_g_new(image,struct_type, n_structs) \
314 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
316 #define image_g_new0(image,struct_type, n_structs) \
317 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
320 static void
321 alloc_table (MonoDynamicTable *table, guint nrows)
323 table->rows = nrows;
324 g_assert (table->columns);
325 if (nrows + 1 >= table->alloc_rows) {
326 while (nrows + 1 >= table->alloc_rows) {
327 if (table->alloc_rows == 0)
328 table->alloc_rows = 16;
329 else
330 table->alloc_rows *= 2;
333 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
337 static void
338 make_room_in_stream (MonoDynamicStream *stream, int size)
340 if (size <= stream->alloc_size)
341 return;
343 while (stream->alloc_size <= size) {
344 if (stream->alloc_size < 4096)
345 stream->alloc_size = 4096;
346 else
347 stream->alloc_size *= 2;
350 stream->data = g_realloc (stream->data, stream->alloc_size);
353 static guint32
354 string_heap_insert (MonoDynamicStream *sh, const char *str)
356 guint32 idx;
357 guint32 len;
358 gpointer oldkey, oldval;
360 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
361 return GPOINTER_TO_UINT (oldval);
363 len = strlen (str) + 1;
364 idx = sh->index;
366 make_room_in_stream (sh, idx + len);
369 * We strdup the string even if we already copy them in sh->data
370 * so that the string pointers in the hash remain valid even if
371 * we need to realloc sh->data. We may want to avoid that later.
373 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
374 memcpy (sh->data + idx, str, len);
375 sh->index += len;
376 return idx;
379 static guint32
380 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
382 char *name = mono_string_to_utf8 (str);
383 guint32 idx;
384 idx = string_heap_insert (sh, name);
385 g_free (name);
386 return idx;
389 #ifndef DISABLE_REFLECTION_EMIT
390 static void
391 string_heap_init (MonoDynamicStream *sh)
393 sh->index = 0;
394 sh->alloc_size = 4096;
395 sh->data = g_malloc (4096);
396 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
397 string_heap_insert (sh, "");
399 #endif
401 static guint32
402 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
404 guint32 idx;
406 make_room_in_stream (stream, stream->index + len);
407 memcpy (stream->data + stream->index, data, len);
408 idx = stream->index;
409 stream->index += len;
411 * align index? Not without adding an additional param that controls it since
412 * we may store a blob value in pieces.
414 return idx;
417 static guint32
418 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
420 guint32 idx;
422 make_room_in_stream (stream, stream->index + len);
423 memset (stream->data + stream->index, 0, len);
424 idx = stream->index;
425 stream->index += len;
426 return idx;
429 static void
430 stream_data_align (MonoDynamicStream *stream)
432 char buf [4] = {0};
433 guint32 count = stream->index % 4;
435 /* we assume the stream data will be aligned */
436 if (count)
437 mono_image_add_stream_data (stream, buf, 4 - count);
440 #ifndef DISABLE_REFLECTION_EMIT
441 static int
442 mono_blob_entry_hash (const char* str)
444 guint len, h;
445 const char *end;
446 len = mono_metadata_decode_blob_size (str, &str);
447 if (len > 0) {
448 end = str + len;
449 h = *str;
450 for (str += 1; str < end; str++)
451 h = (h << 5) - h + *str;
452 return h;
453 } else {
454 return 0;
458 static gboolean
459 mono_blob_entry_equal (const char *str1, const char *str2) {
460 int len, len2;
461 const char *end1;
462 const char *end2;
463 len = mono_metadata_decode_blob_size (str1, &end1);
464 len2 = mono_metadata_decode_blob_size (str2, &end2);
465 if (len != len2)
466 return 0;
467 return memcmp (end1, end2, len) == 0;
469 #endif
470 static guint32
471 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
473 guint32 idx;
474 char *copy;
475 gpointer oldkey, oldval;
477 copy = g_malloc (s1+s2);
478 memcpy (copy, b1, s1);
479 memcpy (copy + s1, b2, s2);
480 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
481 g_free (copy);
482 idx = GPOINTER_TO_UINT (oldval);
483 } else {
484 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
485 mono_image_add_stream_data (&assembly->blob, b2, s2);
486 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
488 return idx;
491 static guint32
492 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
494 char blob_size [8];
495 char *b = blob_size;
496 guint32 size = buf->p - buf->buf;
497 /* store length */
498 g_assert (size <= (buf->end - buf->buf));
499 mono_metadata_encode_value (size, b, &b);
500 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
504 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
505 * dest may be misaligned.
507 static void
508 swap_with_size (char *dest, const char* val, int len, int nelem) {
509 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
510 int elem;
512 for (elem = 0; elem < nelem; ++elem) {
513 switch (len) {
514 case 1:
515 *dest = *val;
516 break;
517 case 2:
518 dest [0] = val [1];
519 dest [1] = val [0];
520 break;
521 case 4:
522 dest [0] = val [3];
523 dest [1] = val [2];
524 dest [2] = val [1];
525 dest [3] = val [0];
526 break;
527 case 8:
528 dest [0] = val [7];
529 dest [1] = val [6];
530 dest [2] = val [5];
531 dest [3] = val [4];
532 dest [4] = val [3];
533 dest [5] = val [2];
534 dest [6] = val [1];
535 dest [7] = val [0];
536 break;
537 default:
538 g_assert_not_reached ();
540 dest += len;
541 val += len;
543 #else
544 memcpy (dest, val, len * nelem);
545 #endif
548 static guint32
549 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
551 char blob_size [64];
552 char *b = blob_size;
553 guint32 idx = 0, len;
555 len = str->length * 2;
556 mono_metadata_encode_value (len, b, &b);
557 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
559 char *swapped = g_malloc (2 * mono_string_length (str));
560 const char *p = (const char*)mono_string_chars (str);
562 swap_with_size (swapped, p, 2, mono_string_length (str));
563 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
564 g_free (swapped);
566 #else
567 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
568 #endif
569 return idx;
572 #ifndef DISABLE_REFLECTION_EMIT
573 static MonoClass *
574 default_class_from_mono_type (MonoType *type)
576 switch (type->type) {
577 case MONO_TYPE_OBJECT:
578 return mono_defaults.object_class;
579 case MONO_TYPE_VOID:
580 return mono_defaults.void_class;
581 case MONO_TYPE_BOOLEAN:
582 return mono_defaults.boolean_class;
583 case MONO_TYPE_CHAR:
584 return mono_defaults.char_class;
585 case MONO_TYPE_I1:
586 return mono_defaults.sbyte_class;
587 case MONO_TYPE_U1:
588 return mono_defaults.byte_class;
589 case MONO_TYPE_I2:
590 return mono_defaults.int16_class;
591 case MONO_TYPE_U2:
592 return mono_defaults.uint16_class;
593 case MONO_TYPE_I4:
594 return mono_defaults.int32_class;
595 case MONO_TYPE_U4:
596 return mono_defaults.uint32_class;
597 case MONO_TYPE_I:
598 return mono_defaults.int_class;
599 case MONO_TYPE_U:
600 return mono_defaults.uint_class;
601 case MONO_TYPE_I8:
602 return mono_defaults.int64_class;
603 case MONO_TYPE_U8:
604 return mono_defaults.uint64_class;
605 case MONO_TYPE_R4:
606 return mono_defaults.single_class;
607 case MONO_TYPE_R8:
608 return mono_defaults.double_class;
609 case MONO_TYPE_STRING:
610 return mono_defaults.string_class;
611 default:
612 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
613 g_assert_not_reached ();
616 return NULL;
618 #endif
621 * mono_class_get_ref_info:
623 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
625 gpointer
626 mono_class_get_ref_info (MonoClass *klass)
628 if (klass->ref_info_handle == 0)
629 return NULL;
630 else
631 return mono_gchandle_get_target (klass->ref_info_handle);
634 void
635 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
637 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
638 g_assert (klass->ref_info_handle != 0);
641 void
642 mono_class_free_ref_info (MonoClass *klass)
644 if (klass->ref_info_handle) {
645 mono_gchandle_free (klass->ref_info_handle);
646 klass->ref_info_handle = 0;
650 static void
651 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
653 int i;
654 MonoGenericInst *class_inst;
655 MonoClass *klass;
657 g_assert (gclass);
659 class_inst = gclass->context.class_inst;
661 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
662 klass = gclass->container_class;
663 sigbuffer_add_value (buf, klass->byval_arg.type);
664 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
666 sigbuffer_add_value (buf, class_inst->type_argc);
667 for (i = 0; i < class_inst->type_argc; ++i)
668 encode_type (assembly, class_inst->type_argv [i], buf);
672 static void
673 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
675 if (!type) {
676 g_assert_not_reached ();
677 return;
680 if (type->byref)
681 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
683 switch (type->type){
684 case MONO_TYPE_VOID:
685 case MONO_TYPE_BOOLEAN:
686 case MONO_TYPE_CHAR:
687 case MONO_TYPE_I1:
688 case MONO_TYPE_U1:
689 case MONO_TYPE_I2:
690 case MONO_TYPE_U2:
691 case MONO_TYPE_I4:
692 case MONO_TYPE_U4:
693 case MONO_TYPE_I8:
694 case MONO_TYPE_U8:
695 case MONO_TYPE_R4:
696 case MONO_TYPE_R8:
697 case MONO_TYPE_I:
698 case MONO_TYPE_U:
699 case MONO_TYPE_STRING:
700 case MONO_TYPE_OBJECT:
701 case MONO_TYPE_TYPEDBYREF:
702 sigbuffer_add_value (buf, type->type);
703 break;
704 case MONO_TYPE_PTR:
705 sigbuffer_add_value (buf, type->type);
706 encode_type (assembly, type->data.type, buf);
707 break;
708 case MONO_TYPE_SZARRAY:
709 sigbuffer_add_value (buf, type->type);
710 encode_type (assembly, &type->data.klass->byval_arg, buf);
711 break;
712 case MONO_TYPE_VALUETYPE:
713 case MONO_TYPE_CLASS: {
714 MonoClass *k = mono_class_from_mono_type (type);
716 if (k->generic_container) {
717 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
718 encode_generic_class (assembly, gclass, buf);
719 } else {
721 * Make sure we use the correct type.
723 sigbuffer_add_value (buf, k->byval_arg.type);
725 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
726 * otherwise two typerefs could point to the same type, leading to
727 * verification errors.
729 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
731 break;
733 case MONO_TYPE_ARRAY:
734 sigbuffer_add_value (buf, type->type);
735 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
736 sigbuffer_add_value (buf, type->data.array->rank);
737 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
738 sigbuffer_add_value (buf, 0);
739 break;
740 case MONO_TYPE_GENERICINST:
741 encode_generic_class (assembly, type->data.generic_class, buf);
742 break;
743 case MONO_TYPE_VAR:
744 case MONO_TYPE_MVAR:
745 sigbuffer_add_value (buf, type->type);
746 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
747 break;
748 default:
749 g_error ("need to encode type %x", type->type);
753 static void
754 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
756 if (!type) {
757 sigbuffer_add_value (buf, MONO_TYPE_VOID);
758 return;
761 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
764 static void
765 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
767 int i;
769 if (modreq) {
770 for (i = 0; i < mono_array_length (modreq); ++i) {
771 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
772 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
773 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
776 if (modopt) {
777 for (i = 0; i < mono_array_length (modopt); ++i) {
778 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
779 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
780 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
785 #ifndef DISABLE_REFLECTION_EMIT
786 static guint32
787 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
789 SigBuffer buf;
790 int i;
791 guint32 nparams = sig->param_count;
792 guint32 idx;
794 if (!assembly->save)
795 return 0;
797 sigbuffer_init (&buf, 32);
799 * FIXME: vararg, explicit_this, differenc call_conv values...
801 idx = sig->call_convention;
802 if (sig->hasthis)
803 idx |= 0x20; /* hasthis */
804 if (sig->generic_param_count)
805 idx |= 0x10; /* generic */
806 sigbuffer_add_byte (&buf, idx);
807 if (sig->generic_param_count)
808 sigbuffer_add_value (&buf, sig->generic_param_count);
809 sigbuffer_add_value (&buf, nparams);
810 encode_type (assembly, sig->ret, &buf);
811 for (i = 0; i < nparams; ++i) {
812 if (i == sig->sentinelpos)
813 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
814 encode_type (assembly, sig->params [i], &buf);
816 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
817 sigbuffer_free (&buf);
818 return idx;
820 #endif
822 static guint32
823 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
826 * FIXME: reuse code from method_encode_signature().
828 SigBuffer buf;
829 int i;
830 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
831 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
832 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
833 guint32 idx;
835 sigbuffer_init (&buf, 32);
836 /* LAMESPEC: all the call conv spec is foobared */
837 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
838 if (mb->call_conv & 2)
839 idx |= 0x5; /* vararg */
840 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
841 idx |= 0x20; /* hasthis */
842 if (ngparams)
843 idx |= 0x10; /* generic */
844 sigbuffer_add_byte (&buf, idx);
845 if (ngparams)
846 sigbuffer_add_value (&buf, ngparams);
847 sigbuffer_add_value (&buf, nparams + notypes);
848 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
849 encode_reflection_type (assembly, mb->rtype, &buf);
850 for (i = 0; i < nparams; ++i) {
851 MonoArray *modreq = NULL;
852 MonoArray *modopt = NULL;
853 MonoReflectionType *pt;
855 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
856 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
857 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
858 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
859 encode_custom_modifiers (assembly, modreq, modopt, &buf);
860 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
861 encode_reflection_type (assembly, pt, &buf);
863 if (notypes)
864 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
865 for (i = 0; i < notypes; ++i) {
866 MonoReflectionType *pt;
868 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
869 encode_reflection_type (assembly, pt, &buf);
872 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
873 sigbuffer_free (&buf);
874 return idx;
877 static guint32
878 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
880 MonoDynamicTable *table;
881 guint32 *values;
882 guint32 idx, sig_idx;
883 guint nl = mono_array_length (ilgen->locals);
884 SigBuffer buf;
885 int i;
887 sigbuffer_init (&buf, 32);
888 sigbuffer_add_value (&buf, 0x07);
889 sigbuffer_add_value (&buf, nl);
890 for (i = 0; i < nl; ++i) {
891 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
893 if (lb->is_pinned)
894 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
896 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
898 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
899 sigbuffer_free (&buf);
901 if (assembly->standalonesig_cache == NULL)
902 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
903 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
904 if (idx)
905 return idx;
907 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
908 idx = table->next_idx ++;
909 table->rows ++;
910 alloc_table (table, table->rows);
911 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
913 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
915 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
917 return idx;
920 static guint32
921 method_count_clauses (MonoReflectionILGen *ilgen)
923 guint32 num_clauses = 0;
924 int i;
926 MonoILExceptionInfo *ex_info;
927 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
928 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
929 if (ex_info->handlers)
930 num_clauses += mono_array_length (ex_info->handlers);
931 else
932 num_clauses++;
935 return num_clauses;
938 #ifndef DISABLE_REFLECTION_EMIT
939 static MonoExceptionClause*
940 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
942 MonoExceptionClause *clauses;
943 MonoExceptionClause *clause;
944 MonoILExceptionInfo *ex_info;
945 MonoILExceptionBlock *ex_block;
946 guint32 finally_start;
947 int i, j, clause_index;;
949 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
951 clause_index = 0;
952 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
953 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
954 finally_start = ex_info->start + ex_info->len;
955 if (!ex_info->handlers)
956 continue;
957 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
958 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
959 clause = &(clauses [clause_index]);
961 clause->flags = ex_block->type;
962 clause->try_offset = ex_info->start;
964 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
965 clause->try_len = finally_start - ex_info->start;
966 else
967 clause->try_len = ex_info->len;
968 clause->handler_offset = ex_block->start;
969 clause->handler_len = ex_block->len;
970 if (ex_block->extype) {
971 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
972 } else {
973 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
974 clause->data.filter_offset = ex_block->filter_offset;
975 else
976 clause->data.filter_offset = 0;
978 finally_start = ex_block->start + ex_block->len;
980 clause_index ++;
984 return clauses;
986 #endif /* !DISABLE_REFLECTION_EMIT */
988 static guint32
989 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
991 char flags = 0;
992 guint32 idx;
993 guint32 code_size;
994 gint32 max_stack, i;
995 gint32 num_locals = 0;
996 gint32 num_exception = 0;
997 gint maybe_small;
998 guint32 fat_flags;
999 char fat_header [12];
1000 guint32 int_value;
1001 guint16 short_value;
1002 guint32 local_sig = 0;
1003 guint32 header_size = 12;
1004 MonoArray *code;
1006 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1007 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1008 return 0;
1010 /*if (mb->name)
1011 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1012 if (mb->ilgen) {
1013 code = mb->ilgen->code;
1014 code_size = mb->ilgen->code_len;
1015 max_stack = mb->ilgen->max_stack;
1016 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1017 if (mb->ilgen->ex_handlers)
1018 num_exception = method_count_clauses (mb->ilgen);
1019 } else {
1020 code = mb->code;
1021 if (code == NULL){
1022 char *name = mono_string_to_utf8 (mb->name);
1023 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1024 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1025 g_free (str);
1026 g_free (name);
1027 mono_raise_exception (exception);
1030 code_size = mono_array_length (code);
1031 max_stack = 8; /* we probably need to run a verifier on the code... */
1034 stream_data_align (&assembly->code);
1036 /* check for exceptions, maxstack, locals */
1037 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1038 if (maybe_small) {
1039 if (code_size < 64 && !(code_size & 1)) {
1040 flags = (code_size << 2) | 0x2;
1041 } else if (code_size < 32 && (code_size & 1)) {
1042 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1043 } else {
1044 goto fat_header;
1046 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1047 /* add to the fixup todo list */
1048 if (mb->ilgen && mb->ilgen->num_token_fixups)
1049 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1050 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1051 return assembly->text_rva + idx;
1053 fat_header:
1054 if (num_locals)
1055 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1057 * FIXME: need to set also the header size in fat_flags.
1058 * (and more sects and init locals flags)
1060 fat_flags = 0x03;
1061 if (num_exception)
1062 fat_flags |= METHOD_HEADER_MORE_SECTS;
1063 if (mb->init_locals)
1064 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1065 fat_header [0] = fat_flags;
1066 fat_header [1] = (header_size / 4 ) << 4;
1067 short_value = GUINT16_TO_LE (max_stack);
1068 memcpy (fat_header + 2, &short_value, 2);
1069 int_value = GUINT32_TO_LE (code_size);
1070 memcpy (fat_header + 4, &int_value, 4);
1071 int_value = GUINT32_TO_LE (local_sig);
1072 memcpy (fat_header + 8, &int_value, 4);
1073 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1074 /* add to the fixup todo list */
1075 if (mb->ilgen && mb->ilgen->num_token_fixups)
1076 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1078 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1079 if (num_exception) {
1080 unsigned char sheader [4];
1081 MonoILExceptionInfo * ex_info;
1082 MonoILExceptionBlock * ex_block;
1083 int j;
1085 stream_data_align (&assembly->code);
1086 /* always use fat format for now */
1087 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1088 num_exception *= 6 * sizeof (guint32);
1089 num_exception += 4; /* include the size of the header */
1090 sheader [1] = num_exception & 0xff;
1091 sheader [2] = (num_exception >> 8) & 0xff;
1092 sheader [3] = (num_exception >> 16) & 0xff;
1093 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1094 /* fat header, so we are already aligned */
1095 /* reverse order */
1096 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1097 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1098 if (ex_info->handlers) {
1099 int finally_start = ex_info->start + ex_info->len;
1100 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1101 guint32 val;
1102 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1103 /* the flags */
1104 val = GUINT32_TO_LE (ex_block->type);
1105 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1106 /* try offset */
1107 val = GUINT32_TO_LE (ex_info->start);
1108 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1109 /* need fault, too, probably */
1110 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1111 val = GUINT32_TO_LE (finally_start - ex_info->start);
1112 else
1113 val = GUINT32_TO_LE (ex_info->len);
1114 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1115 /* handler offset */
1116 val = GUINT32_TO_LE (ex_block->start);
1117 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1118 /* handler len */
1119 val = GUINT32_TO_LE (ex_block->len);
1120 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1121 finally_start = ex_block->start + ex_block->len;
1122 if (ex_block->extype) {
1123 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1124 } else {
1125 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1126 val = ex_block->filter_offset;
1127 else
1128 val = 0;
1130 val = GUINT32_TO_LE (val);
1131 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1132 /*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",
1133 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);*/
1135 } else {
1136 g_error ("No clauses for ex info block %d", i);
1140 return assembly->text_rva + idx;
1143 static guint32
1144 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1146 int i;
1147 MonoDynamicTable *table;
1148 guint32 *values;
1150 table = &assembly->tables [table_idx];
1152 g_assert (col < table->columns);
1154 values = table->values + table->columns;
1155 for (i = 1; i <= table->rows; ++i) {
1156 if (values [col] == token)
1157 return i;
1158 values += table->columns;
1160 return 0;
1164 * LOCKING: Acquires the loader lock.
1166 static MonoCustomAttrInfo*
1167 lookup_custom_attr (MonoImage *image, gpointer member)
1169 MonoCustomAttrInfo* res;
1171 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1173 if (!res)
1174 return NULL;
1176 return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1179 static gboolean
1180 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1182 /* FIXME: Need to do more checks */
1183 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1184 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1186 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1187 return FALSE;
1190 return TRUE;
1193 static MonoCustomAttrInfo*
1194 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1196 int i, index, count, not_visible;
1197 MonoCustomAttrInfo *ainfo;
1198 MonoReflectionCustomAttr *cattr;
1200 if (!cattrs)
1201 return NULL;
1202 /* FIXME: check in assembly the Run flag is set */
1204 count = mono_array_length (cattrs);
1206 /* Skip nonpublic attributes since MS.NET seems to do the same */
1207 /* FIXME: This needs to be done more globally */
1208 not_visible = 0;
1209 for (i = 0; i < count; ++i) {
1210 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1211 if (!custom_attr_visible (image, cattr))
1212 not_visible ++;
1214 count -= not_visible;
1216 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1218 ainfo->image = image;
1219 ainfo->num_attrs = count;
1220 ainfo->cached = alloc_img != NULL;
1221 index = 0;
1222 for (i = 0; i < count; ++i) {
1223 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1224 if (custom_attr_visible (image, cattr)) {
1225 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1226 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1227 ainfo->attrs [index].ctor = cattr->ctor->method;
1228 ainfo->attrs [index].data = saved;
1229 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1230 index ++;
1234 return ainfo;
1237 #ifndef DISABLE_REFLECTION_EMIT
1239 * LOCKING: Acquires the loader lock.
1241 static void
1242 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1244 MonoCustomAttrInfo *ainfo, *tmp;
1246 if (!cattrs || !mono_array_length (cattrs))
1247 return;
1249 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1251 mono_loader_lock ();
1252 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1253 if (tmp)
1254 mono_custom_attrs_free (tmp);
1255 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1256 mono_loader_unlock ();
1259 #endif
1261 void
1262 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1264 if (!ainfo->cached)
1265 g_free (ainfo);
1269 * idx is the table index of the object
1270 * type is one of MONO_CUSTOM_ATTR_*
1272 static void
1273 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1275 MonoDynamicTable *table;
1276 MonoReflectionCustomAttr *cattr;
1277 guint32 *values;
1278 guint32 count, i, token;
1279 char blob_size [6];
1280 char *p = blob_size;
1282 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1283 if (!cattrs)
1284 return;
1285 count = mono_array_length (cattrs);
1286 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1287 table->rows += count;
1288 alloc_table (table, table->rows);
1289 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1290 idx <<= MONO_CUSTOM_ATTR_BITS;
1291 idx |= type;
1292 for (i = 0; i < count; ++i) {
1293 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1294 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1295 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1296 type = mono_metadata_token_index (token);
1297 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1298 switch (mono_metadata_token_table (token)) {
1299 case MONO_TABLE_METHOD:
1300 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1301 break;
1302 case MONO_TABLE_MEMBERREF:
1303 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1304 break;
1305 default:
1306 g_warning ("got wrong token in custom attr");
1307 continue;
1309 values [MONO_CUSTOM_ATTR_TYPE] = type;
1310 p = blob_size;
1311 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1312 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1313 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1314 values += MONO_CUSTOM_ATTR_SIZE;
1315 ++table->next_idx;
1319 static void
1320 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1322 MonoDynamicTable *table;
1323 guint32 *values;
1324 guint32 count, i, idx;
1325 MonoReflectionPermissionSet *perm;
1327 if (!permissions)
1328 return;
1330 count = mono_array_length (permissions);
1331 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1332 table->rows += count;
1333 alloc_table (table, table->rows);
1335 for (i = 0; i < mono_array_length (permissions); ++i) {
1336 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1338 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1340 idx = mono_metadata_token_index (parent_token);
1341 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1342 switch (mono_metadata_token_table (parent_token)) {
1343 case MONO_TABLE_TYPEDEF:
1344 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1345 break;
1346 case MONO_TABLE_METHOD:
1347 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1348 break;
1349 case MONO_TABLE_ASSEMBLY:
1350 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1351 break;
1352 default:
1353 g_assert_not_reached ();
1356 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1357 values [MONO_DECL_SECURITY_PARENT] = idx;
1358 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1360 ++table->next_idx;
1365 * Fill in the MethodDef and ParamDef tables for a method.
1366 * This is used for both normal methods and constructors.
1368 static void
1369 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1371 MonoDynamicTable *table;
1372 guint32 *values;
1373 guint i, count;
1375 /* room in this table is already allocated */
1376 table = &assembly->tables [MONO_TABLE_METHOD];
1377 *mb->table_idx = table->next_idx ++;
1378 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1379 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1380 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1381 values [MONO_METHOD_FLAGS] = mb->attrs;
1382 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1383 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1384 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1386 table = &assembly->tables [MONO_TABLE_PARAM];
1387 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1389 mono_image_add_decl_security (assembly,
1390 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1392 if (mb->pinfo) {
1393 MonoDynamicTable *mtable;
1394 guint32 *mvalues;
1396 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1397 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1399 count = 0;
1400 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1401 if (mono_array_get (mb->pinfo, gpointer, i))
1402 count++;
1404 table->rows += count;
1405 alloc_table (table, table->rows);
1406 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1407 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1408 MonoReflectionParamBuilder *pb;
1409 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1410 values [MONO_PARAM_FLAGS] = pb->attrs;
1411 values [MONO_PARAM_SEQUENCE] = i;
1412 if (pb->name != NULL) {
1413 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1414 } else {
1415 values [MONO_PARAM_NAME] = 0;
1417 values += MONO_PARAM_SIZE;
1418 if (pb->marshal_info) {
1419 mtable->rows++;
1420 alloc_table (mtable, mtable->rows);
1421 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1422 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1423 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1425 pb->table_idx = table->next_idx++;
1426 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1427 guint32 field_type = 0;
1428 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1429 mtable->rows ++;
1430 alloc_table (mtable, mtable->rows);
1431 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1432 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1433 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1434 mvalues [MONO_CONSTANT_TYPE] = field_type;
1435 mvalues [MONO_CONSTANT_PADDING] = 0;
1442 #ifndef DISABLE_REFLECTION_EMIT
1443 static void
1444 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1446 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1448 rmb->ilgen = mb->ilgen;
1449 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1450 rmb->parameters = mb->parameters;
1451 rmb->generic_params = mb->generic_params;
1452 rmb->generic_container = mb->generic_container;
1453 rmb->opt_types = NULL;
1454 rmb->pinfo = mb->pinfo;
1455 rmb->attrs = mb->attrs;
1456 rmb->iattrs = mb->iattrs;
1457 rmb->call_conv = mb->call_conv;
1458 rmb->code = mb->code;
1459 rmb->type = mb->type;
1460 rmb->name = mb->name;
1461 rmb->table_idx = &mb->table_idx;
1462 rmb->init_locals = mb->init_locals;
1463 rmb->skip_visibility = FALSE;
1464 rmb->return_modreq = mb->return_modreq;
1465 rmb->return_modopt = mb->return_modopt;
1466 rmb->param_modreq = mb->param_modreq;
1467 rmb->param_modopt = mb->param_modopt;
1468 rmb->permissions = mb->permissions;
1469 rmb->mhandle = mb->mhandle;
1470 rmb->nrefs = 0;
1471 rmb->refs = NULL;
1473 if (mb->dll) {
1474 rmb->charset = mb->charset;
1475 rmb->extra_flags = mb->extra_flags;
1476 rmb->native_cc = mb->native_cc;
1477 rmb->dllentry = mb->dllentry;
1478 rmb->dll = mb->dll;
1482 static void
1483 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1485 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1487 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1489 rmb->ilgen = mb->ilgen;
1490 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1491 rmb->parameters = mb->parameters;
1492 rmb->generic_params = NULL;
1493 rmb->generic_container = NULL;
1494 rmb->opt_types = NULL;
1495 rmb->pinfo = mb->pinfo;
1496 rmb->attrs = mb->attrs;
1497 rmb->iattrs = mb->iattrs;
1498 rmb->call_conv = mb->call_conv;
1499 rmb->code = NULL;
1500 rmb->type = mb->type;
1501 rmb->name = mono_string_new (mono_domain_get (), name);
1502 rmb->table_idx = &mb->table_idx;
1503 rmb->init_locals = mb->init_locals;
1504 rmb->skip_visibility = FALSE;
1505 rmb->return_modreq = NULL;
1506 rmb->return_modopt = NULL;
1507 rmb->param_modreq = mb->param_modreq;
1508 rmb->param_modopt = mb->param_modopt;
1509 rmb->permissions = mb->permissions;
1510 rmb->mhandle = mb->mhandle;
1511 rmb->nrefs = 0;
1512 rmb->refs = NULL;
1515 static void
1516 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1518 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1520 rmb->ilgen = mb->ilgen;
1521 rmb->rtype = mb->rtype;
1522 rmb->parameters = mb->parameters;
1523 rmb->generic_params = NULL;
1524 rmb->generic_container = NULL;
1525 rmb->opt_types = NULL;
1526 rmb->pinfo = NULL;
1527 rmb->attrs = mb->attrs;
1528 rmb->iattrs = 0;
1529 rmb->call_conv = mb->call_conv;
1530 rmb->code = NULL;
1531 rmb->type = (MonoObject *) mb->owner;
1532 rmb->name = mb->name;
1533 rmb->table_idx = NULL;
1534 rmb->init_locals = mb->init_locals;
1535 rmb->skip_visibility = mb->skip_visibility;
1536 rmb->return_modreq = NULL;
1537 rmb->return_modopt = NULL;
1538 rmb->param_modreq = NULL;
1539 rmb->param_modopt = NULL;
1540 rmb->permissions = NULL;
1541 rmb->mhandle = mb->mhandle;
1542 rmb->nrefs = 0;
1543 rmb->refs = NULL;
1545 #endif
1547 static void
1548 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1550 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1551 MonoDynamicTable *table;
1552 guint32 *values;
1553 guint32 tok;
1555 if (!mb->override_method)
1556 return;
1558 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1559 table->rows ++;
1560 alloc_table (table, table->rows);
1561 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1562 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1563 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1565 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1566 switch (mono_metadata_token_table (tok)) {
1567 case MONO_TABLE_MEMBERREF:
1568 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1569 break;
1570 case MONO_TABLE_METHOD:
1571 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1572 break;
1573 default:
1574 g_assert_not_reached ();
1576 values [MONO_METHODIMPL_DECLARATION] = tok;
1579 #ifndef DISABLE_REFLECTION_EMIT
1580 static void
1581 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1583 MonoDynamicTable *table;
1584 guint32 *values;
1585 ReflectionMethodBuilder rmb;
1586 int i;
1588 reflection_methodbuilder_from_method_builder (&rmb, mb);
1590 mono_image_basic_method (&rmb, assembly);
1591 mb->table_idx = *rmb.table_idx;
1593 if (mb->dll) { /* It's a P/Invoke method */
1594 guint32 moduleref;
1595 /* map CharSet values to on-disk values */
1596 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1597 int extra_flags = mb->extra_flags;
1598 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1599 table->rows ++;
1600 alloc_table (table, table->rows);
1601 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1603 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1604 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1605 if (mb->dllentry)
1606 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1607 else
1608 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1609 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1610 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1611 table = &assembly->tables [MONO_TABLE_MODULEREF];
1612 table->rows ++;
1613 alloc_table (table, table->rows);
1614 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1615 values [MONO_IMPLMAP_SCOPE] = table->rows;
1619 if (mb->generic_params) {
1620 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1621 table->rows += mono_array_length (mb->generic_params);
1622 alloc_table (table, table->rows);
1623 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1624 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1626 mono_image_get_generic_param_info (
1627 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1633 static void
1634 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1636 ReflectionMethodBuilder rmb;
1638 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1640 mono_image_basic_method (&rmb, assembly);
1641 mb->table_idx = *rmb.table_idx;
1643 #endif
1645 static char*
1646 type_get_fully_qualified_name (MonoType *type)
1648 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1651 static char*
1652 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1653 MonoClass *klass;
1654 MonoAssembly *ta;
1656 klass = mono_class_from_mono_type (type);
1657 if (!klass)
1658 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1659 ta = klass->image->assembly;
1660 if (ta->dynamic || (ta == ass)) {
1661 if (klass->generic_class || klass->generic_container)
1662 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1663 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1664 else
1665 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1668 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1671 #ifndef DISABLE_REFLECTION_EMIT
1672 /*field_image is the image to which the eventual custom mods have been encoded against*/
1673 static guint32
1674 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1676 SigBuffer buf;
1677 guint32 idx, i, token;
1679 if (!assembly->save)
1680 return 0;
1682 sigbuffer_init (&buf, 32);
1684 sigbuffer_add_value (&buf, 0x06);
1685 /* encode custom attributes before the type */
1686 if (type->num_mods) {
1687 for (i = 0; i < type->num_mods; ++i) {
1688 if (field_image) {
1689 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1690 g_assert (class);
1691 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1692 } else {
1693 token = type->modifiers [i].token;
1696 if (type->modifiers [i].required)
1697 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1698 else
1699 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1701 sigbuffer_add_value (&buf, token);
1704 encode_type (assembly, type, &buf);
1705 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1706 sigbuffer_free (&buf);
1707 return idx;
1709 #endif
1711 static guint32
1712 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1714 SigBuffer buf;
1715 guint32 idx;
1717 sigbuffer_init (&buf, 32);
1719 sigbuffer_add_value (&buf, 0x06);
1720 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1721 /* encode custom attributes before the type */
1722 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1723 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1724 sigbuffer_free (&buf);
1725 return idx;
1728 static guint32
1729 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1730 char blob_size [64];
1731 char *b = blob_size;
1732 char *p, *box_val;
1733 char* buf;
1734 guint32 idx = 0, len = 0, dummy = 0;
1735 #ifdef ARM_FPU_FPA
1736 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1737 guint32 fpa_double [2];
1738 guint32 *fpa_p;
1739 #endif
1740 #endif
1742 p = buf = g_malloc (64);
1743 if (!val) {
1744 *ret_type = MONO_TYPE_CLASS;
1745 len = 4;
1746 box_val = (char*)&dummy;
1747 } else {
1748 box_val = ((char*)val) + sizeof (MonoObject);
1749 *ret_type = val->vtable->klass->byval_arg.type;
1751 handle_enum:
1752 switch (*ret_type) {
1753 case MONO_TYPE_BOOLEAN:
1754 case MONO_TYPE_U1:
1755 case MONO_TYPE_I1:
1756 len = 1;
1757 break;
1758 case MONO_TYPE_CHAR:
1759 case MONO_TYPE_U2:
1760 case MONO_TYPE_I2:
1761 len = 2;
1762 break;
1763 case MONO_TYPE_U4:
1764 case MONO_TYPE_I4:
1765 case MONO_TYPE_R4:
1766 len = 4;
1767 break;
1768 case MONO_TYPE_U8:
1769 case MONO_TYPE_I8:
1770 len = 8;
1771 break;
1772 case MONO_TYPE_R8:
1773 len = 8;
1774 #ifdef ARM_FPU_FPA
1775 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1776 fpa_p = (guint32*)box_val;
1777 fpa_double [0] = fpa_p [1];
1778 fpa_double [1] = fpa_p [0];
1779 box_val = (char*)fpa_double;
1780 #endif
1781 #endif
1782 break;
1783 case MONO_TYPE_VALUETYPE: {
1784 MonoClass *klass = val->vtable->klass;
1786 if (klass->enumtype) {
1787 *ret_type = mono_class_enum_basetype (klass)->type;
1788 goto handle_enum;
1789 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1790 len = 8;
1791 } else
1792 g_error ("we can't encode valuetypes, we should have never reached this line");
1793 break;
1795 case MONO_TYPE_CLASS:
1796 break;
1797 case MONO_TYPE_STRING: {
1798 MonoString *str = (MonoString*)val;
1799 /* there is no signature */
1800 len = str->length * 2;
1801 mono_metadata_encode_value (len, b, &b);
1802 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1804 char *swapped = g_malloc (2 * mono_string_length (str));
1805 const char *p = (const char*)mono_string_chars (str);
1807 swap_with_size (swapped, p, 2, mono_string_length (str));
1808 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1809 g_free (swapped);
1811 #else
1812 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1813 #endif
1815 g_free (buf);
1816 return idx;
1818 case MONO_TYPE_GENERICINST:
1819 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1820 goto handle_enum;
1821 default:
1822 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1825 /* there is no signature */
1826 mono_metadata_encode_value (len, b, &b);
1827 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1828 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1829 swap_with_size (blob_size, box_val, len, 1);
1830 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1831 #else
1832 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1833 #endif
1835 g_free (buf);
1836 return idx;
1839 static guint32
1840 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1841 char *str;
1842 SigBuffer buf;
1843 guint32 idx, len;
1845 sigbuffer_init (&buf, 32);
1847 sigbuffer_add_value (&buf, minfo->type);
1849 switch (minfo->type) {
1850 case MONO_NATIVE_BYVALTSTR:
1851 case MONO_NATIVE_BYVALARRAY:
1852 sigbuffer_add_value (&buf, minfo->count);
1853 break;
1854 case MONO_NATIVE_LPARRAY:
1855 if (minfo->eltype || minfo->has_size) {
1856 sigbuffer_add_value (&buf, minfo->eltype);
1857 if (minfo->has_size) {
1858 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1859 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1861 /* LAMESPEC: ElemMult is undocumented */
1862 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1865 break;
1866 case MONO_NATIVE_SAFEARRAY:
1867 if (minfo->eltype)
1868 sigbuffer_add_value (&buf, minfo->eltype);
1869 break;
1870 case MONO_NATIVE_CUSTOM:
1871 if (minfo->guid) {
1872 str = mono_string_to_utf8 (minfo->guid);
1873 len = strlen (str);
1874 sigbuffer_add_value (&buf, len);
1875 sigbuffer_add_mem (&buf, str, len);
1876 g_free (str);
1877 } else {
1878 sigbuffer_add_value (&buf, 0);
1880 /* native type name */
1881 sigbuffer_add_value (&buf, 0);
1882 /* custom marshaler type name */
1883 if (minfo->marshaltype || minfo->marshaltyperef) {
1884 if (minfo->marshaltyperef)
1885 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1886 else
1887 str = mono_string_to_utf8 (minfo->marshaltype);
1888 len = strlen (str);
1889 sigbuffer_add_value (&buf, len);
1890 sigbuffer_add_mem (&buf, str, len);
1891 g_free (str);
1892 } else {
1893 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1894 sigbuffer_add_value (&buf, 0);
1896 if (minfo->mcookie) {
1897 str = mono_string_to_utf8 (minfo->mcookie);
1898 len = strlen (str);
1899 sigbuffer_add_value (&buf, len);
1900 sigbuffer_add_mem (&buf, str, len);
1901 g_free (str);
1902 } else {
1903 sigbuffer_add_value (&buf, 0);
1905 break;
1906 default:
1907 break;
1909 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1910 sigbuffer_free (&buf);
1911 return idx;
1914 static void
1915 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1917 MonoDynamicTable *table;
1918 guint32 *values;
1920 /* maybe this fixup should be done in the C# code */
1921 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1922 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1923 table = &assembly->tables [MONO_TABLE_FIELD];
1924 fb->table_idx = table->next_idx ++;
1925 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1926 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1927 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1928 values [MONO_FIELD_FLAGS] = fb->attrs;
1929 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1931 if (fb->offset != -1) {
1932 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1933 table->rows ++;
1934 alloc_table (table, table->rows);
1935 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1936 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1937 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1939 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1940 guint32 field_type = 0;
1941 table = &assembly->tables [MONO_TABLE_CONSTANT];
1942 table->rows ++;
1943 alloc_table (table, table->rows);
1944 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1945 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1946 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1947 values [MONO_CONSTANT_TYPE] = field_type;
1948 values [MONO_CONSTANT_PADDING] = 0;
1950 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1951 guint32 rva_idx;
1952 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1953 table->rows ++;
1954 alloc_table (table, table->rows);
1955 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1956 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1958 * We store it in the code section because it's simpler for now.
1960 if (fb->rva_data) {
1961 if (mono_array_length (fb->rva_data) >= 10)
1962 stream_data_align (&assembly->code);
1963 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1964 } else
1965 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1966 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1968 if (fb->marshal_info) {
1969 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1970 table->rows ++;
1971 alloc_table (table, table->rows);
1972 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1973 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1974 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1978 static guint32
1979 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1981 SigBuffer buf;
1982 guint32 nparams = 0;
1983 MonoReflectionMethodBuilder *mb = fb->get_method;
1984 MonoReflectionMethodBuilder *smb = fb->set_method;
1985 guint32 idx, i;
1987 if (mb && mb->parameters)
1988 nparams = mono_array_length (mb->parameters);
1989 if (!mb && smb && smb->parameters)
1990 nparams = mono_array_length (smb->parameters) - 1;
1991 sigbuffer_init (&buf, 32);
1992 if (fb->call_conv & 0x20)
1993 sigbuffer_add_byte (&buf, 0x28);
1994 else
1995 sigbuffer_add_byte (&buf, 0x08);
1996 sigbuffer_add_value (&buf, nparams);
1997 if (mb) {
1998 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
1999 for (i = 0; i < nparams; ++i) {
2000 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2001 encode_reflection_type (assembly, pt, &buf);
2003 } else if (smb && smb->parameters) {
2004 /* the property type is the last param */
2005 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2006 for (i = 0; i < nparams; ++i) {
2007 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2008 encode_reflection_type (assembly, pt, &buf);
2010 } else {
2011 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2014 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2015 sigbuffer_free (&buf);
2016 return idx;
2019 static void
2020 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2022 MonoDynamicTable *table;
2023 guint32 *values;
2024 guint num_methods = 0;
2025 guint32 semaidx;
2028 * we need to set things in the following tables:
2029 * PROPERTYMAP (info already filled in _get_type_info ())
2030 * PROPERTY (rows already preallocated in _get_type_info ())
2031 * METHOD (method info already done with the generic method code)
2032 * METHODSEMANTICS
2033 * CONSTANT
2035 table = &assembly->tables [MONO_TABLE_PROPERTY];
2036 pb->table_idx = table->next_idx ++;
2037 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2038 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2039 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2040 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2042 /* FIXME: we still don't handle 'other' methods */
2043 if (pb->get_method) num_methods ++;
2044 if (pb->set_method) num_methods ++;
2046 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2047 table->rows += num_methods;
2048 alloc_table (table, table->rows);
2050 if (pb->get_method) {
2051 semaidx = table->next_idx ++;
2052 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2053 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2054 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2055 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2057 if (pb->set_method) {
2058 semaidx = table->next_idx ++;
2059 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2060 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2061 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2062 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2064 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2065 guint32 field_type = 0;
2066 table = &assembly->tables [MONO_TABLE_CONSTANT];
2067 table->rows ++;
2068 alloc_table (table, table->rows);
2069 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2070 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2071 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2072 values [MONO_CONSTANT_TYPE] = field_type;
2073 values [MONO_CONSTANT_PADDING] = 0;
2077 static void
2078 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2080 MonoDynamicTable *table;
2081 guint32 *values;
2082 guint num_methods = 0;
2083 guint32 semaidx;
2086 * we need to set things in the following tables:
2087 * EVENTMAP (info already filled in _get_type_info ())
2088 * EVENT (rows already preallocated in _get_type_info ())
2089 * METHOD (method info already done with the generic method code)
2090 * METHODSEMANTICS
2092 table = &assembly->tables [MONO_TABLE_EVENT];
2093 eb->table_idx = table->next_idx ++;
2094 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2095 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2096 values [MONO_EVENT_FLAGS] = eb->attrs;
2097 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2100 * FIXME: we still don't handle 'other' methods
2102 if (eb->add_method) num_methods ++;
2103 if (eb->remove_method) num_methods ++;
2104 if (eb->raise_method) num_methods ++;
2106 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2107 table->rows += num_methods;
2108 alloc_table (table, table->rows);
2110 if (eb->add_method) {
2111 semaidx = table->next_idx ++;
2112 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2113 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2114 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2115 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2117 if (eb->remove_method) {
2118 semaidx = table->next_idx ++;
2119 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2120 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2121 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2122 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2124 if (eb->raise_method) {
2125 semaidx = table->next_idx ++;
2126 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2127 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2128 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2129 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2133 static void
2134 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2136 MonoDynamicTable *table;
2137 guint32 num_constraints, i;
2138 guint32 *values;
2139 guint32 table_idx;
2141 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2142 num_constraints = gparam->iface_constraints ?
2143 mono_array_length (gparam->iface_constraints) : 0;
2144 table->rows += num_constraints;
2145 if (gparam->base_type)
2146 table->rows++;
2147 alloc_table (table, table->rows);
2149 if (gparam->base_type) {
2150 table_idx = table->next_idx ++;
2151 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2153 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2154 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2155 assembly, mono_reflection_type_get_handle (gparam->base_type));
2158 for (i = 0; i < num_constraints; i++) {
2159 MonoReflectionType *constraint = mono_array_get (
2160 gparam->iface_constraints, gpointer, i);
2162 table_idx = table->next_idx ++;
2163 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2165 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2166 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2167 assembly, mono_reflection_type_get_handle (constraint));
2171 static void
2172 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2174 GenericParamTableEntry *entry;
2177 * The GenericParam table must be sorted according to the `owner' field.
2178 * We need to do this sorting prior to writing the GenericParamConstraint
2179 * table, since we have to use the final GenericParam table indices there
2180 * and they must also be sorted.
2183 entry = g_new0 (GenericParamTableEntry, 1);
2184 entry->owner = owner;
2185 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2186 MOVING_GC_REGISTER (&entry->gparam);
2187 entry->gparam = gparam;
2189 g_ptr_array_add (assembly->gen_params, entry);
2192 static void
2193 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2195 MonoDynamicTable *table;
2196 MonoGenericParam *param;
2197 guint32 *values;
2198 guint32 table_idx;
2200 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2201 table_idx = table->next_idx ++;
2202 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2204 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2206 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2207 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2208 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2209 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2211 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2213 encode_constraints (entry->gparam, table_idx, assembly);
2216 static guint32
2217 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2219 MonoDynamicTable *table;
2220 guint32 token;
2221 guint32 *values;
2222 guint32 cols [MONO_ASSEMBLY_SIZE];
2223 const char *pubkey;
2224 guint32 publen;
2226 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2227 return token;
2229 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2230 table = &assembly->tables [MONO_TABLE_MODULEREF];
2231 token = table->next_idx ++;
2232 table->rows ++;
2233 alloc_table (table, table->rows);
2234 values = table->values + token * MONO_MODULEREF_SIZE;
2235 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2237 token <<= MONO_RESOLTION_SCOPE_BITS;
2238 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2239 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2241 return token;
2244 if (image->assembly->dynamic)
2245 /* FIXME: */
2246 memset (cols, 0, sizeof (cols));
2247 else {
2248 /* image->assembly->image is the manifest module */
2249 image = image->assembly->image;
2250 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2253 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2254 token = table->next_idx ++;
2255 table->rows ++;
2256 alloc_table (table, table->rows);
2257 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2258 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2259 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2260 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2261 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2262 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2263 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2264 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2265 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2267 if (strcmp ("", image->assembly->aname.culture)) {
2268 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2269 image->assembly->aname.culture);
2272 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2273 guchar pubtoken [9];
2274 pubtoken [0] = 8;
2275 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2276 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2277 } else {
2278 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2280 token <<= MONO_RESOLTION_SCOPE_BITS;
2281 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2282 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2283 return token;
2286 static guint32
2287 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2289 MonoDynamicTable *table;
2290 guint32 *values;
2291 guint32 token;
2292 SigBuffer buf;
2294 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2295 return token;
2297 sigbuffer_init (&buf, 32);
2298 switch (type->type) {
2299 case MONO_TYPE_FNPTR:
2300 case MONO_TYPE_PTR:
2301 case MONO_TYPE_SZARRAY:
2302 case MONO_TYPE_ARRAY:
2303 case MONO_TYPE_VAR:
2304 case MONO_TYPE_MVAR:
2305 case MONO_TYPE_GENERICINST:
2306 encode_type (assembly, type, &buf);
2307 break;
2308 case MONO_TYPE_CLASS:
2309 case MONO_TYPE_VALUETYPE: {
2310 MonoClass *k = mono_class_from_mono_type (type);
2311 if (!k || !k->generic_container) {
2312 sigbuffer_free (&buf);
2313 return 0;
2315 encode_type (assembly, type, &buf);
2316 break;
2318 default:
2319 sigbuffer_free (&buf);
2320 return 0;
2323 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2324 if (assembly->save) {
2325 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2326 alloc_table (table, table->rows + 1);
2327 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2328 values [MONO_TYPESPEC_SIGNATURE] = token;
2330 sigbuffer_free (&buf);
2332 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2333 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2334 table->next_idx ++;
2335 return token;
2338 static guint32
2339 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2341 MonoDynamicTable *table;
2342 guint32 *values;
2343 guint32 token, scope, enclosing;
2344 MonoClass *klass;
2346 /* if the type requires a typespec, we must try that first*/
2347 if (try_typespec && (token = create_typespec (assembly, type)))
2348 return token;
2349 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2350 if (token)
2351 return token;
2352 klass = mono_class_from_mono_type (type);
2353 if (!klass)
2354 klass = mono_class_from_mono_type (type);
2357 * If it's in the same module and not a generic type parameter:
2359 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2360 (type->type != MONO_TYPE_MVAR)) {
2361 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2362 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2363 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2364 return token;
2367 if (klass->nested_in) {
2368 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2369 /* get the typeref idx of the enclosing type */
2370 enclosing >>= MONO_TYPEDEFORREF_BITS;
2371 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2372 } else {
2373 scope = resolution_scope_from_image (assembly, klass->image);
2375 table = &assembly->tables [MONO_TABLE_TYPEREF];
2376 if (assembly->save) {
2377 alloc_table (table, table->rows + 1);
2378 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2379 values [MONO_TYPEREF_SCOPE] = scope;
2380 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2381 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2383 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2384 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2385 table->next_idx ++;
2386 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2387 return token;
2391 * Despite the name, we handle also TypeSpec (with the above helper).
2393 static guint32
2394 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2396 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2399 #ifndef DISABLE_REFLECTION_EMIT
2400 static guint32
2401 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2403 MonoDynamicTable *table;
2404 guint32 *values;
2405 guint32 token, pclass;
2407 switch (parent & MONO_TYPEDEFORREF_MASK) {
2408 case MONO_TYPEDEFORREF_TYPEREF:
2409 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2410 break;
2411 case MONO_TYPEDEFORREF_TYPESPEC:
2412 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2413 break;
2414 case MONO_TYPEDEFORREF_TYPEDEF:
2415 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2416 break;
2417 default:
2418 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2419 return 0;
2421 /* extract the index */
2422 parent >>= MONO_TYPEDEFORREF_BITS;
2424 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2426 if (assembly->save) {
2427 alloc_table (table, table->rows + 1);
2428 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2429 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2430 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2431 values [MONO_MEMBERREF_SIGNATURE] = sig;
2434 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2435 table->next_idx ++;
2437 return token;
2441 * Insert a memberef row into the metadata: the token that point to the memberref
2442 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2443 * mono_image_get_fieldref_token()).
2444 * The sig param is an index to an already built signature.
2446 static guint32
2447 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2449 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2450 return mono_image_add_memberef_row (assembly, parent, name, sig);
2454 static guint32
2455 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2457 guint32 token;
2458 MonoMethodSignature *sig;
2460 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2462 if (create_typespec) {
2463 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2464 if (token)
2465 return token;
2468 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2469 if (token && !create_typespec)
2470 return token;
2472 g_assert (!method->is_inflated);
2473 if (!token) {
2475 * A methodref signature can't contain an unmanaged calling convention.
2477 sig = mono_metadata_signature_dup (mono_method_signature (method));
2478 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2479 sig->call_convention = MONO_CALL_DEFAULT;
2480 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2481 method->name, method_encode_signature (assembly, sig));
2482 g_free (sig);
2483 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2486 if (create_typespec) {
2487 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2488 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2489 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2491 if (assembly->save) {
2492 guint32 *values;
2494 alloc_table (table, table->rows + 1);
2495 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2496 values [MONO_METHODSPEC_METHOD] = token;
2497 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2500 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2501 table->next_idx ++;
2502 /*methodspec and memberef tokens are diferent, */
2503 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2504 return token;
2506 return token;
2509 static guint32
2510 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2512 guint32 token, parent, sig;
2513 ReflectionMethodBuilder rmb;
2514 char *name;
2515 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2517 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2518 if (token)
2519 return token;
2521 name = mono_string_to_utf8 (method->name);
2522 reflection_methodbuilder_from_method_builder (&rmb, method);
2525 * A methodref signature can't contain an unmanaged calling convention.
2526 * Since some flags are encoded as part of call_conv, we need to check against it.
2528 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2529 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2531 sig = method_builder_encode_signature (assembly, &rmb);
2533 if (tb->generic_params)
2534 parent = create_generic_typespec (assembly, tb);
2535 else
2536 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2538 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2540 g_free (name);
2541 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2542 return token;
2545 static guint32
2546 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2547 const gchar *name, guint32 sig)
2549 MonoDynamicTable *table;
2550 guint32 token;
2551 guint32 *values;
2553 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2555 if (assembly->save) {
2556 alloc_table (table, table->rows + 1);
2557 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2558 values [MONO_MEMBERREF_CLASS] = original;
2559 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2560 values [MONO_MEMBERREF_SIGNATURE] = sig;
2563 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2564 table->next_idx ++;
2566 return token;
2569 static guint32
2570 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2572 SigBuffer buf;
2573 int i;
2574 guint32 nparams = mono_array_length (mb->generic_params);
2575 guint32 idx;
2577 if (!assembly->save)
2578 return 0;
2580 sigbuffer_init (&buf, 32);
2582 sigbuffer_add_value (&buf, 0xa);
2583 sigbuffer_add_value (&buf, nparams);
2585 for (i = 0; i < nparams; i++) {
2586 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2587 sigbuffer_add_value (&buf, i);
2590 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2591 sigbuffer_free (&buf);
2592 return idx;
2595 static guint32
2596 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2598 MonoDynamicTable *table;
2599 guint32 *values;
2600 guint32 token, mtoken = 0;
2602 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2603 if (token)
2604 return token;
2606 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2608 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2609 switch (mono_metadata_token_table (mtoken)) {
2610 case MONO_TABLE_MEMBERREF:
2611 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2612 break;
2613 case MONO_TABLE_METHOD:
2614 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2615 break;
2616 default:
2617 g_assert_not_reached ();
2620 if (assembly->save) {
2621 alloc_table (table, table->rows + 1);
2622 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2623 values [MONO_METHODSPEC_METHOD] = mtoken;
2624 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2627 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2628 table->next_idx ++;
2630 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2631 return token;
2634 static guint32
2635 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2637 guint32 token;
2639 if (mb->generic_params && create_methodspec)
2640 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2642 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2643 if (token)
2644 return token;
2646 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2647 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2648 return token;
2651 static guint32
2652 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2654 guint32 token, parent, sig;
2655 ReflectionMethodBuilder rmb;
2656 char *name;
2657 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2659 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2660 if (token)
2661 return token;
2663 g_assert (tb->generic_params);
2665 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2667 parent = create_generic_typespec (assembly, tb);
2668 name = mono_string_to_utf8 (rmb.name);
2669 sig = method_builder_encode_signature (assembly, &rmb);
2671 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2673 g_free (name);
2674 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2675 return token;
2677 #endif
2679 static gboolean
2680 is_field_on_inst (MonoClassField *field)
2682 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2686 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2688 static MonoType*
2689 get_field_on_inst_generic_type (MonoClassField *field)
2691 MonoClass *class, *gtd;
2692 MonoDynamicGenericClass *dgclass;
2693 int field_index;
2695 g_assert (is_field_on_inst (field));
2697 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2699 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2700 field_index = field - dgclass->fields;
2701 return dgclass->field_generic_types [field_index];
2704 class = field->parent;
2705 gtd = class->generic_class->container_class;
2707 if (field >= class->fields && field - class->fields < class->field.count) {
2708 field_index = field - class->fields;
2709 return gtd->fields [field_index].type;
2712 g_assert_not_reached ();
2713 return 0;
2716 #ifndef DISABLE_REFLECTION_EMIT
2717 static guint32
2718 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2720 MonoType *type;
2721 guint32 token;
2723 g_assert (field);
2724 g_assert (field->parent);
2726 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2727 if (token)
2728 return token;
2730 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2731 int index = field - field->parent->fields;
2732 type = field->parent->generic_class->container_class->fields [index].type;
2733 } else {
2734 if (is_field_on_inst (field))
2735 type = get_field_on_inst_generic_type (field);
2736 else
2737 type = field->type;
2739 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2740 mono_field_get_name (field),
2741 fieldref_encode_signature (assembly, field->parent->image, type));
2742 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2743 return token;
2746 static guint32
2747 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2749 guint32 token;
2750 MonoClass *klass;
2751 MonoGenericClass *gclass;
2752 MonoDynamicGenericClass *dgclass;
2753 MonoType *type;
2754 char *name;
2756 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2757 if (token)
2758 return token;
2759 if (is_sre_field_builder (mono_object_class (f->fb))) {
2760 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2761 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2762 klass = mono_class_from_mono_type (type);
2763 gclass = type->data.generic_class;
2764 g_assert (gclass->is_dynamic);
2765 dgclass = (MonoDynamicGenericClass *) gclass;
2767 name = mono_string_to_utf8 (fb->name);
2768 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2769 field_encode_signature (assembly, fb));
2770 g_free (name);
2771 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2772 guint32 sig;
2773 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2775 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2776 klass = mono_class_from_mono_type (type);
2778 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2779 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2780 } else {
2781 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2782 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2785 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2786 return token;
2789 static guint32
2790 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2792 guint32 sig, token;
2793 MonoClass *klass;
2794 MonoGenericClass *gclass;
2795 MonoType *type;
2797 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2799 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2800 if (token)
2801 return token;
2803 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2804 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2805 MonoDynamicGenericClass *dgclass;
2806 ReflectionMethodBuilder rmb;
2807 char *name;
2809 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2810 klass = mono_class_from_mono_type (type);
2812 gclass = type->data.generic_class;
2813 g_assert (gclass->is_dynamic);
2814 dgclass = (MonoDynamicGenericClass *) gclass;
2816 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2818 name = mono_string_to_utf8 (rmb.name);
2820 sig = method_builder_encode_signature (assembly, &rmb);
2822 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2823 g_free (name);
2824 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2825 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2827 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2828 klass = mono_class_from_mono_type (type);
2830 sig = method_encode_signature (assembly, mono_method_signature (mm));
2831 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2832 } else {
2833 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2834 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2838 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2839 return token;
2842 static MonoMethod*
2843 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2845 MonoClass *klass;
2846 MonoGenericContext tmp_context;
2847 MonoType **type_argv;
2848 MonoGenericInst *ginst;
2849 MonoMethod *method, *inflated;
2850 int count, i;
2852 method = inflate_method (m->inst, (MonoObject*)m->mb);
2854 klass = method->klass;
2856 if (m->method_args == NULL)
2857 return method;
2859 if (method->is_inflated)
2860 method = ((MonoMethodInflated *) method)->declaring;
2862 count = mono_array_length (m->method_args);
2864 type_argv = g_new0 (MonoType *, count);
2865 for (i = 0; i < count; i++) {
2866 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2867 type_argv [i] = mono_reflection_type_get_handle (garg);
2869 ginst = mono_metadata_get_generic_inst (count, type_argv);
2870 g_free (type_argv);
2872 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2873 tmp_context.method_inst = ginst;
2875 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2876 return inflated;
2879 static guint32
2880 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2882 guint32 sig, token = 0;
2883 MonoType *type;
2884 MonoClass *klass;
2886 if (m->method_args) {
2887 MonoMethod *inflated;
2889 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2890 if (create_methodspec)
2891 token = mono_image_get_methodspec_token (assembly, inflated);
2892 else
2893 token = mono_image_get_inflated_method_token (assembly, inflated);
2894 return token;
2897 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2898 if (token)
2899 return token;
2901 if (is_sre_method_builder (mono_object_class (m->mb))) {
2902 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2903 MonoGenericClass *gclass;
2904 ReflectionMethodBuilder rmb;
2905 char *name;
2907 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2908 klass = mono_class_from_mono_type (type);
2909 gclass = type->data.generic_class;
2910 g_assert (gclass->is_dynamic);
2912 reflection_methodbuilder_from_method_builder (&rmb, mb);
2914 name = mono_string_to_utf8 (rmb.name);
2916 sig = method_builder_encode_signature (assembly, &rmb);
2918 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2919 g_free (name);
2920 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2921 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2923 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2924 klass = mono_class_from_mono_type (type);
2926 sig = method_encode_signature (assembly, mono_method_signature (mm));
2927 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2928 } else {
2929 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2930 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2933 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2934 return token;
2937 static guint32
2938 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2940 SigBuffer buf;
2941 int i;
2942 guint32 nparams = context->method_inst->type_argc;
2943 guint32 idx;
2945 if (!assembly->save)
2946 return 0;
2948 sigbuffer_init (&buf, 32);
2950 * FIXME: vararg, explicit_this, differenc call_conv values...
2952 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2953 sigbuffer_add_value (&buf, nparams);
2955 for (i = 0; i < nparams; i++)
2956 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2958 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2959 sigbuffer_free (&buf);
2960 return idx;
2963 static guint32
2964 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2966 MonoDynamicTable *table;
2967 guint32 *values;
2968 guint32 token, mtoken = 0, sig;
2969 MonoMethodInflated *imethod;
2970 MonoMethod *declaring;
2972 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2974 g_assert (method->is_inflated);
2975 imethod = (MonoMethodInflated *) method;
2976 declaring = imethod->declaring;
2978 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2979 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2981 if (!mono_method_signature (declaring)->generic_param_count)
2982 return mtoken;
2984 switch (mono_metadata_token_table (mtoken)) {
2985 case MONO_TABLE_MEMBERREF:
2986 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2987 break;
2988 case MONO_TABLE_METHOD:
2989 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2990 break;
2991 default:
2992 g_assert_not_reached ();
2995 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2997 if (assembly->save) {
2998 alloc_table (table, table->rows + 1);
2999 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3000 values [MONO_METHODSPEC_METHOD] = mtoken;
3001 values [MONO_METHODSPEC_SIGNATURE] = sig;
3004 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3005 table->next_idx ++;
3007 return token;
3010 static guint32
3011 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3013 MonoMethodInflated *imethod;
3014 guint32 token;
3016 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3017 if (token)
3018 return token;
3020 g_assert (method->is_inflated);
3021 imethod = (MonoMethodInflated *) method;
3023 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3024 token = method_encode_methodspec (assembly, method);
3025 } else {
3026 guint32 sig = method_encode_signature (
3027 assembly, mono_method_signature (imethod->declaring));
3028 token = mono_image_get_memberref_token (
3029 assembly, &method->klass->byval_arg, method->name, sig);
3032 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3033 return token;
3036 static guint32
3037 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3039 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3040 guint32 sig, token;
3042 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3043 token = mono_image_get_memberref_token (
3044 assembly, &m->klass->byval_arg, m->name, sig);
3046 return token;
3049 static guint32
3050 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3052 MonoDynamicTable *table;
3053 MonoClass *klass;
3054 MonoType *type;
3055 guint32 *values;
3056 guint32 token;
3057 SigBuffer buf;
3058 int count, i;
3061 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3062 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3063 * Because of this, we must not insert it into the `typeref' hash table.
3065 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3066 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3067 if (token)
3068 return token;
3070 sigbuffer_init (&buf, 32);
3072 g_assert (tb->generic_params);
3073 klass = mono_class_from_mono_type (type);
3075 if (tb->generic_container)
3076 mono_reflection_create_generic_class (tb);
3078 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3079 g_assert (klass->generic_container);
3080 sigbuffer_add_value (&buf, klass->byval_arg.type);
3081 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3083 count = mono_array_length (tb->generic_params);
3084 sigbuffer_add_value (&buf, count);
3085 for (i = 0; i < count; i++) {
3086 MonoReflectionGenericParam *gparam;
3088 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3090 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3093 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3095 if (assembly->save) {
3096 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3097 alloc_table (table, table->rows + 1);
3098 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3099 values [MONO_TYPESPEC_SIGNATURE] = token;
3101 sigbuffer_free (&buf);
3103 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3104 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3105 table->next_idx ++;
3106 return token;
3110 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3112 static MonoType*
3113 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3115 int i, count, len, pos;
3116 MonoType *t;
3118 count = 0;
3119 if (modreq)
3120 count += mono_array_length (modreq);
3121 if (modopt)
3122 count += mono_array_length (modopt);
3124 if (count == 0)
3125 return mono_metadata_type_dup (NULL, type);
3127 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3128 t = g_malloc (len);
3129 memcpy (t, type, MONO_SIZEOF_TYPE);
3131 t->num_mods = count;
3132 pos = 0;
3133 if (modreq) {
3134 for (i = 0; i < mono_array_length (modreq); ++i) {
3135 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3136 t->modifiers [pos].required = 1;
3137 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3138 pos ++;
3141 if (modopt) {
3142 for (i = 0; i < mono_array_length (modopt); ++i) {
3143 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3144 t->modifiers [pos].required = 0;
3145 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3146 pos ++;
3150 return t;
3153 static guint32
3154 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3156 MonoDynamicTable *table;
3157 MonoClass *klass;
3158 MonoType *custom = NULL;
3159 guint32 *values;
3160 guint32 token, pclass, parent, sig;
3161 gchar *name;
3163 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3164 if (token)
3165 return token;
3167 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3168 name = mono_string_to_utf8 (fb->name);
3170 /* fb->type does not include the custom modifiers */
3171 /* FIXME: We should do this in one place when a fieldbuilder is created */
3172 if (fb->modreq || fb->modopt) {
3173 custom = add_custom_modifiers (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type), fb->modreq, fb->modopt);
3174 sig = fieldref_encode_signature (assembly, NULL, custom);
3175 g_free (custom);
3176 } else {
3177 sig = fieldref_encode_signature (assembly, NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
3180 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3181 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3183 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3184 parent >>= MONO_TYPEDEFORREF_BITS;
3186 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3188 if (assembly->save) {
3189 alloc_table (table, table->rows + 1);
3190 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3191 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3192 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3193 values [MONO_MEMBERREF_SIGNATURE] = sig;
3196 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3197 table->next_idx ++;
3198 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3199 g_free (name);
3200 return token;
3203 static guint32
3204 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3206 SigBuffer buf;
3207 guint32 nargs;
3208 guint32 size;
3209 guint32 i, idx;
3211 if (!assembly->save)
3212 return 0;
3214 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3215 g_assert (helper->type == 2);
3217 if (helper->arguments)
3218 nargs = mono_array_length (helper->arguments);
3219 else
3220 nargs = 0;
3222 size = 10 + (nargs * 10);
3224 sigbuffer_init (&buf, 32);
3226 /* Encode calling convention */
3227 /* Change Any to Standard */
3228 if ((helper->call_conv & 0x03) == 0x03)
3229 helper->call_conv = 0x01;
3230 /* explicit_this implies has_this */
3231 if (helper->call_conv & 0x40)
3232 helper->call_conv &= 0x20;
3234 if (helper->call_conv == 0) { /* Unmanaged */
3235 idx = helper->unmanaged_call_conv - 1;
3236 } else {
3237 /* Managed */
3238 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3239 if (helper->call_conv & 0x02) /* varargs */
3240 idx += 0x05;
3243 sigbuffer_add_byte (&buf, idx);
3244 sigbuffer_add_value (&buf, nargs);
3245 encode_reflection_type (assembly, helper->return_type, &buf);
3246 for (i = 0; i < nargs; ++i) {
3247 MonoArray *modreqs = NULL;
3248 MonoArray *modopts = NULL;
3249 MonoReflectionType *pt;
3251 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3252 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3253 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3254 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3256 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3257 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3258 encode_reflection_type (assembly, pt, &buf);
3260 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3261 sigbuffer_free (&buf);
3263 return idx;
3266 static guint32
3267 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3269 guint32 idx;
3270 MonoDynamicTable *table;
3271 guint32 *values;
3273 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3274 idx = table->next_idx ++;
3275 table->rows ++;
3276 alloc_table (table, table->rows);
3277 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3279 values [MONO_STAND_ALONE_SIGNATURE] =
3280 mono_reflection_encode_sighelper (assembly, helper);
3282 return idx;
3285 static int
3286 reflection_cc_to_file (int call_conv) {
3287 switch (call_conv & 0x3) {
3288 case 0:
3289 case 1: return MONO_CALL_DEFAULT;
3290 case 2: return MONO_CALL_VARARG;
3291 default:
3292 g_assert_not_reached ();
3294 return 0;
3296 #endif /* !DISABLE_REFLECTION_EMIT */
3298 typedef struct {
3299 MonoType *parent;
3300 MonoMethodSignature *sig;
3301 char *name;
3302 guint32 token;
3303 } ArrayMethod;
3305 #ifndef DISABLE_REFLECTION_EMIT
3306 static guint32
3307 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3309 guint32 nparams, i;
3310 GList *tmp;
3311 char *name;
3312 MonoMethodSignature *sig;
3313 ArrayMethod *am;
3314 MonoType *mtype;
3316 name = mono_string_to_utf8 (m->name);
3317 nparams = mono_array_length (m->parameters);
3318 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3319 sig->hasthis = 1;
3320 sig->sentinelpos = -1;
3321 sig->call_convention = reflection_cc_to_file (m->call_conv);
3322 sig->param_count = nparams;
3323 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3324 mtype = mono_reflection_type_get_handle (m->parent);
3325 for (i = 0; i < nparams; ++i)
3326 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3328 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3329 am = tmp->data;
3330 if (strcmp (name, am->name) == 0 &&
3331 mono_metadata_type_equal (am->parent, mtype) &&
3332 mono_metadata_signature_equal (am->sig, sig)) {
3333 g_free (name);
3334 g_free (sig);
3335 m->table_idx = am->token & 0xffffff;
3336 return am->token;
3339 am = g_new0 (ArrayMethod, 1);
3340 am->name = name;
3341 am->sig = sig;
3342 am->parent = mtype;
3343 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3344 method_encode_signature (assembly, sig));
3345 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3346 m->table_idx = am->token & 0xffffff;
3347 return am->token;
3351 * Insert into the metadata tables all the info about the TypeBuilder tb.
3352 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3354 static void
3355 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3357 MonoDynamicTable *table;
3358 guint *values;
3359 int i, is_object = 0, is_system = 0;
3360 char *n;
3362 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3363 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3364 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3365 n = mono_string_to_utf8 (tb->name);
3366 if (strcmp (n, "Object") == 0)
3367 is_object++;
3368 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3369 g_free (n);
3370 n = mono_string_to_utf8 (tb->nspace);
3371 if (strcmp (n, "System") == 0)
3372 is_system++;
3373 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3374 g_free (n);
3375 if (tb->parent && !(is_system && is_object) &&
3376 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3377 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3378 } else {
3379 values [MONO_TYPEDEF_EXTENDS] = 0;
3381 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3382 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3385 * if we have explicitlayout or sequentiallayouts, output data in the
3386 * ClassLayout table.
3388 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3389 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3390 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3391 table->rows++;
3392 alloc_table (table, table->rows);
3393 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3394 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3395 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3396 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3399 /* handle interfaces */
3400 if (tb->interfaces) {
3401 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3402 i = table->rows;
3403 table->rows += mono_array_length (tb->interfaces);
3404 alloc_table (table, table->rows);
3405 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3406 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3407 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3408 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3409 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3410 values += MONO_INTERFACEIMPL_SIZE;
3414 /* handle fields */
3415 if (tb->fields) {
3416 table = &assembly->tables [MONO_TABLE_FIELD];
3417 table->rows += tb->num_fields;
3418 alloc_table (table, table->rows);
3419 for (i = 0; i < tb->num_fields; ++i)
3420 mono_image_get_field_info (
3421 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3424 /* handle constructors */
3425 if (tb->ctors) {
3426 table = &assembly->tables [MONO_TABLE_METHOD];
3427 table->rows += mono_array_length (tb->ctors);
3428 alloc_table (table, table->rows);
3429 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3430 mono_image_get_ctor_info (domain,
3431 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3434 /* handle methods */
3435 if (tb->methods) {
3436 table = &assembly->tables [MONO_TABLE_METHOD];
3437 table->rows += tb->num_methods;
3438 alloc_table (table, table->rows);
3439 for (i = 0; i < tb->num_methods; ++i)
3440 mono_image_get_method_info (
3441 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3444 /* Do the same with properties etc.. */
3445 if (tb->events && mono_array_length (tb->events)) {
3446 table = &assembly->tables [MONO_TABLE_EVENT];
3447 table->rows += mono_array_length (tb->events);
3448 alloc_table (table, table->rows);
3449 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3450 table->rows ++;
3451 alloc_table (table, table->rows);
3452 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3453 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3454 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3455 for (i = 0; i < mono_array_length (tb->events); ++i)
3456 mono_image_get_event_info (
3457 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3459 if (tb->properties && mono_array_length (tb->properties)) {
3460 table = &assembly->tables [MONO_TABLE_PROPERTY];
3461 table->rows += mono_array_length (tb->properties);
3462 alloc_table (table, table->rows);
3463 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3464 table->rows ++;
3465 alloc_table (table, table->rows);
3466 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3467 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3468 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3469 for (i = 0; i < mono_array_length (tb->properties); ++i)
3470 mono_image_get_property_info (
3471 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3474 /* handle generic parameters */
3475 if (tb->generic_params) {
3476 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3477 table->rows += mono_array_length (tb->generic_params);
3478 alloc_table (table, table->rows);
3479 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3480 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3482 mono_image_get_generic_param_info (
3483 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3487 mono_image_add_decl_security (assembly,
3488 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3490 if (tb->subtypes) {
3491 MonoDynamicTable *ntable;
3493 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3494 ntable->rows += mono_array_length (tb->subtypes);
3495 alloc_table (ntable, ntable->rows);
3496 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3498 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3499 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3501 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3502 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3503 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3504 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3505 mono_string_to_utf8 (tb->name), tb->table_idx,
3506 ntable->next_idx, ntable->rows);*/
3507 values += MONO_NESTED_CLASS_SIZE;
3508 ntable->next_idx++;
3512 #endif
3514 static void
3515 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3517 int i;
3519 mono_ptr_array_append (*types, type);
3521 if (!type->subtypes)
3522 return;
3524 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3525 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3526 collect_types (types, subtype);
3530 static gint
3531 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3533 if ((*type1)->table_idx < (*type2)->table_idx)
3534 return -1;
3535 else
3536 if ((*type1)->table_idx > (*type2)->table_idx)
3537 return 1;
3538 else
3539 return 0;
3542 static void
3543 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3544 int i;
3546 if (!pinfo)
3547 return;
3548 for (i = 0; i < mono_array_length (pinfo); ++i) {
3549 MonoReflectionParamBuilder *pb;
3550 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3551 if (!pb)
3552 continue;
3553 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3557 static void
3558 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3559 int i;
3561 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3562 if (tb->fields) {
3563 for (i = 0; i < tb->num_fields; ++i) {
3564 MonoReflectionFieldBuilder* fb;
3565 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3566 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3569 if (tb->events) {
3570 for (i = 0; i < mono_array_length (tb->events); ++i) {
3571 MonoReflectionEventBuilder* eb;
3572 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3573 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3576 if (tb->properties) {
3577 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3578 MonoReflectionPropertyBuilder* pb;
3579 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3580 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3583 if (tb->ctors) {
3584 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3585 MonoReflectionCtorBuilder* cb;
3586 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3587 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3588 params_add_cattrs (assembly, cb->pinfo);
3592 if (tb->methods) {
3593 for (i = 0; i < tb->num_methods; ++i) {
3594 MonoReflectionMethodBuilder* mb;
3595 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3596 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3597 params_add_cattrs (assembly, mb->pinfo);
3601 if (tb->subtypes) {
3602 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3603 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3607 static void
3608 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3610 int i;
3612 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3614 if (moduleb->global_methods) {
3615 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3616 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3617 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3618 params_add_cattrs (assembly, mb->pinfo);
3622 if (moduleb->global_fields) {
3623 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3624 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3625 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3629 if (moduleb->types) {
3630 for (i = 0; i < moduleb->num_types; ++i)
3631 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3635 static void
3636 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3638 MonoDynamicTable *table;
3639 guint32 *values;
3640 char blob_size [6];
3641 guchar hash [20];
3642 char *b = blob_size;
3643 char *dir, *path;
3645 table = &assembly->tables [MONO_TABLE_FILE];
3646 table->rows++;
3647 alloc_table (table, table->rows);
3648 values = table->values + table->next_idx * MONO_FILE_SIZE;
3649 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3650 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3651 if (module->image->dynamic) {
3652 /* This depends on the fact that the main module is emitted last */
3653 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3654 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3655 } else {
3656 dir = NULL;
3657 path = g_strdup (module->image->name);
3659 mono_sha1_get_digest_from_file (path, hash);
3660 g_free (dir);
3661 g_free (path);
3662 mono_metadata_encode_value (20, b, &b);
3663 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3664 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3665 table->next_idx ++;
3668 static void
3669 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3671 MonoDynamicTable *table;
3672 int i;
3674 table = &assembly->tables [MONO_TABLE_MODULE];
3675 mb->table_idx = table->next_idx ++;
3676 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3677 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3678 i /= 16;
3679 ++i;
3680 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3681 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3682 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3683 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3686 static guint32
3687 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3688 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3690 MonoDynamicTable *table;
3691 guint32 *values;
3692 guint32 visib, res;
3694 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3695 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3696 return 0;
3698 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3699 table->rows++;
3700 alloc_table (table, table->rows);
3701 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3703 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3704 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3705 if (klass->nested_in)
3706 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3707 else
3708 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3709 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3710 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3712 res = table->next_idx;
3714 table->next_idx ++;
3716 /* Emit nested types */
3717 if (klass->ext && klass->ext->nested_classes) {
3718 GList *tmp;
3720 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3721 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3724 return res;
3727 static void
3728 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3729 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3731 MonoClass *klass;
3732 guint32 idx, i;
3734 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3736 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3738 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3739 parent_index, assembly);
3742 * Emit nested types
3743 * We need to do this ourselves since klass->nested_classes is not set up.
3745 if (tb->subtypes) {
3746 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3747 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3751 static void
3752 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3753 guint32 module_index, MonoDynamicImage *assembly)
3755 MonoImage *image = module->image;
3756 MonoTableInfo *t;
3757 guint32 i;
3759 t = &image->tables [MONO_TABLE_TYPEDEF];
3761 for (i = 0; i < t->rows; ++i) {
3762 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3764 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3765 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3769 static void
3770 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3772 MonoDynamicTable *table;
3773 guint32 *values;
3774 guint32 scope, scope_idx, impl, current_idx;
3775 gboolean forwarder = TRUE;
3776 gpointer iter = NULL;
3777 MonoClass *nested;
3779 if (klass->nested_in) {
3780 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3781 forwarder = FALSE;
3782 } else {
3783 scope = resolution_scope_from_image (assembly, klass->image);
3784 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3785 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3786 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3789 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3791 table->rows++;
3792 alloc_table (table, table->rows);
3793 current_idx = table->next_idx;
3794 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3796 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3797 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3798 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3799 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3800 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3802 table->next_idx++;
3804 while ((nested = mono_class_get_nested_types (klass, &iter)))
3805 add_exported_type (assemblyb, assembly, nested, current_idx);
3808 static void
3809 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3811 MonoClass *klass;
3812 int i;
3814 if (!assemblyb->type_forwarders)
3815 return;
3817 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3818 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3819 MonoType *type;
3820 if (!t)
3821 continue;
3823 type = mono_reflection_type_get_handle (t);
3824 g_assert (type);
3826 klass = mono_class_from_mono_type (type);
3828 add_exported_type (assemblyb, assembly, klass, 0);
3832 #define align_pointer(base,p)\
3833 do {\
3834 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3835 if (__diff & 3)\
3836 (p) += 4 - (__diff & 3);\
3837 } while (0)
3839 static int
3840 compare_constants (const void *a, const void *b)
3842 const guint32 *a_values = a;
3843 const guint32 *b_values = b;
3844 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3847 static int
3848 compare_semantics (const void *a, const void *b)
3850 const guint32 *a_values = a;
3851 const guint32 *b_values = b;
3852 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3853 if (assoc)
3854 return assoc;
3855 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3858 static int
3859 compare_custom_attrs (const void *a, const void *b)
3861 const guint32 *a_values = a;
3862 const guint32 *b_values = b;
3864 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3867 static int
3868 compare_field_marshal (const void *a, const void *b)
3870 const guint32 *a_values = a;
3871 const guint32 *b_values = b;
3873 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3876 static int
3877 compare_nested (const void *a, const void *b)
3879 const guint32 *a_values = a;
3880 const guint32 *b_values = b;
3882 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3885 static int
3886 compare_genericparam (const void *a, const void *b)
3888 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3889 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3891 if ((*b_entry)->owner == (*a_entry)->owner)
3892 return
3893 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3894 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3895 else
3896 return (*a_entry)->owner - (*b_entry)->owner;
3899 static int
3900 compare_declsecurity_attrs (const void *a, const void *b)
3902 const guint32 *a_values = a;
3903 const guint32 *b_values = b;
3905 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3908 static int
3909 compare_interface_impl (const void *a, const void *b)
3911 const guint32 *a_values = a;
3912 const guint32 *b_values = b;
3914 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3915 if (klass)
3916 return klass;
3918 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3921 static void
3922 pad_heap (MonoDynamicStream *sh)
3924 if (sh->index & 3) {
3925 int sz = 4 - (sh->index & 3);
3926 memset (sh->data + sh->index, 0, sz);
3927 sh->index += sz;
3931 struct StreamDesc {
3932 const char *name;
3933 MonoDynamicStream *stream;
3937 * build_compressed_metadata() fills in the blob of data that represents the
3938 * raw metadata as it will be saved in the PE file. The five streams are output
3939 * and the metadata tables are comnpressed from the guint32 array representation,
3940 * to the compressed on-disk format.
3942 static void
3943 build_compressed_metadata (MonoDynamicImage *assembly)
3945 MonoDynamicTable *table;
3946 int i;
3947 guint64 valid_mask = 0;
3948 guint64 sorted_mask;
3949 guint32 heapt_size = 0;
3950 guint32 meta_size = 256; /* allow for header and other stuff */
3951 guint32 table_offset;
3952 guint32 ntables = 0;
3953 guint64 *int64val;
3954 guint32 *int32val;
3955 guint16 *int16val;
3956 MonoImage *meta;
3957 unsigned char *p;
3958 struct StreamDesc stream_desc [5];
3960 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3961 for (i = 0; i < assembly->gen_params->len; i++){
3962 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3963 write_generic_param_entry (assembly, entry);
3966 stream_desc [0].name = "#~";
3967 stream_desc [0].stream = &assembly->tstream;
3968 stream_desc [1].name = "#Strings";
3969 stream_desc [1].stream = &assembly->sheap;
3970 stream_desc [2].name = "#US";
3971 stream_desc [2].stream = &assembly->us;
3972 stream_desc [3].name = "#Blob";
3973 stream_desc [3].stream = &assembly->blob;
3974 stream_desc [4].name = "#GUID";
3975 stream_desc [4].stream = &assembly->guid;
3977 /* tables that are sorted */
3978 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3979 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3980 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3981 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3982 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3983 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3984 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3986 /* Compute table sizes */
3987 /* the MonoImage has already been created in mono_image_basic_init() */
3988 meta = &assembly->image;
3990 /* sizes should be multiple of 4 */
3991 pad_heap (&assembly->blob);
3992 pad_heap (&assembly->guid);
3993 pad_heap (&assembly->sheap);
3994 pad_heap (&assembly->us);
3996 /* Setup the info used by compute_sizes () */
3997 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3998 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3999 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4001 meta_size += assembly->blob.index;
4002 meta_size += assembly->guid.index;
4003 meta_size += assembly->sheap.index;
4004 meta_size += assembly->us.index;
4006 for (i=0; i < MONO_TABLE_NUM; ++i)
4007 meta->tables [i].rows = assembly->tables [i].rows;
4009 for (i = 0; i < MONO_TABLE_NUM; i++){
4010 if (meta->tables [i].rows == 0)
4011 continue;
4012 valid_mask |= (guint64)1 << i;
4013 ntables ++;
4014 meta->tables [i].row_size = mono_metadata_compute_size (
4015 meta, i, &meta->tables [i].size_bitfield);
4016 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4018 heapt_size += 24; /* #~ header size */
4019 heapt_size += ntables * 4;
4020 /* make multiple of 4 */
4021 heapt_size += 3;
4022 heapt_size &= ~3;
4023 meta_size += heapt_size;
4024 meta->raw_metadata = g_malloc0 (meta_size);
4025 p = (unsigned char*)meta->raw_metadata;
4026 /* the metadata signature */
4027 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4028 /* version numbers and 4 bytes reserved */
4029 int16val = (guint16*)p;
4030 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4031 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4032 p += 8;
4033 /* version string */
4034 int32val = (guint32*)p;
4035 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4036 p += 4;
4037 memcpy (p, meta->version, strlen (meta->version));
4038 p += GUINT32_FROM_LE (*int32val);
4039 align_pointer (meta->raw_metadata, p);
4040 int16val = (guint16*)p;
4041 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4042 *int16val = GUINT16_TO_LE (5); /* number of streams */
4043 p += 4;
4046 * write the stream info.
4048 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4049 table_offset += 3; table_offset &= ~3;
4051 assembly->tstream.index = heapt_size;
4052 for (i = 0; i < 5; ++i) {
4053 int32val = (guint32*)p;
4054 stream_desc [i].stream->offset = table_offset;
4055 *int32val++ = GUINT32_TO_LE (table_offset);
4056 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4057 table_offset += GUINT32_FROM_LE (*int32val);
4058 table_offset += 3; table_offset &= ~3;
4059 p += 8;
4060 strcpy ((char*)p, stream_desc [i].name);
4061 p += strlen (stream_desc [i].name) + 1;
4062 align_pointer (meta->raw_metadata, p);
4065 * now copy the data, the table stream header and contents goes first.
4067 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4068 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4069 int32val = (guint32*)p;
4070 *int32val = GUINT32_TO_LE (0); /* reserved */
4071 p += 4;
4073 *p++ = 2; /* version */
4074 *p++ = 0;
4076 if (meta->idx_string_wide)
4077 *p |= 0x01;
4078 if (meta->idx_guid_wide)
4079 *p |= 0x02;
4080 if (meta->idx_blob_wide)
4081 *p |= 0x04;
4082 ++p;
4083 *p++ = 1; /* reserved */
4084 int64val = (guint64*)p;
4085 *int64val++ = GUINT64_TO_LE (valid_mask);
4086 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4087 p += 16;
4088 int32val = (guint32*)p;
4089 for (i = 0; i < MONO_TABLE_NUM; i++){
4090 if (meta->tables [i].rows == 0)
4091 continue;
4092 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4094 p = (unsigned char*)int32val;
4096 /* sort the tables that still need sorting */
4097 table = &assembly->tables [MONO_TABLE_CONSTANT];
4098 if (table->rows)
4099 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4100 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4101 if (table->rows)
4102 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4103 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4104 if (table->rows)
4105 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4106 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4107 if (table->rows)
4108 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4109 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4110 if (table->rows)
4111 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4112 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4113 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4114 if (table->rows)
4115 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4116 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4117 if (table->rows)
4118 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4120 /* compress the tables */
4121 for (i = 0; i < MONO_TABLE_NUM; i++){
4122 int row, col;
4123 guint32 *values;
4124 guint32 bitfield = meta->tables [i].size_bitfield;
4125 if (!meta->tables [i].rows)
4126 continue;
4127 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4128 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4129 meta->tables [i].base = (char*)p;
4130 for (row = 1; row <= meta->tables [i].rows; ++row) {
4131 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4132 for (col = 0; col < assembly->tables [i].columns; ++col) {
4133 switch (mono_metadata_table_size (bitfield, col)) {
4134 case 1:
4135 *p++ = values [col];
4136 break;
4137 case 2:
4138 *p++ = values [col] & 0xff;
4139 *p++ = (values [col] >> 8) & 0xff;
4140 break;
4141 case 4:
4142 *p++ = values [col] & 0xff;
4143 *p++ = (values [col] >> 8) & 0xff;
4144 *p++ = (values [col] >> 16) & 0xff;
4145 *p++ = (values [col] >> 24) & 0xff;
4146 break;
4147 default:
4148 g_assert_not_reached ();
4152 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4155 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4156 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4157 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4158 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4159 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4161 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4165 * Some tables in metadata need to be sorted according to some criteria, but
4166 * when methods and fields are first created with reflection, they may be assigned a token
4167 * that doesn't correspond to the final token they will get assigned after the sorting.
4168 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4169 * with the reflection objects that represent them. Once all the tables are set up, the
4170 * reflection objects will contains the correct table index. fixup_method() will fixup the
4171 * tokens for the method with ILGenerator @ilgen.
4173 static void
4174 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4176 guint32 code_idx = GPOINTER_TO_UINT (value);
4177 MonoReflectionILTokenInfo *iltoken;
4178 MonoReflectionFieldBuilder *field;
4179 MonoReflectionCtorBuilder *ctor;
4180 MonoReflectionMethodBuilder *method;
4181 MonoReflectionTypeBuilder *tb;
4182 MonoReflectionArrayMethod *am;
4183 guint32 i, idx = 0;
4184 unsigned char *target;
4186 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4187 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4188 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4189 switch (target [3]) {
4190 case MONO_TABLE_FIELD:
4191 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4192 field = (MonoReflectionFieldBuilder *)iltoken->member;
4193 idx = field->table_idx;
4194 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4195 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4196 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4197 } else {
4198 g_assert_not_reached ();
4200 break;
4201 case MONO_TABLE_METHOD:
4202 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4203 method = (MonoReflectionMethodBuilder *)iltoken->member;
4204 idx = method->table_idx;
4205 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4206 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4207 idx = ctor->table_idx;
4208 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4209 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4210 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4211 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4212 } else {
4213 g_assert_not_reached ();
4215 break;
4216 case MONO_TABLE_TYPEDEF:
4217 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4218 g_assert_not_reached ();
4219 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4220 idx = tb->table_idx;
4221 break;
4222 case MONO_TABLE_MEMBERREF:
4223 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4224 am = (MonoReflectionArrayMethod*)iltoken->member;
4225 idx = am->table_idx;
4226 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4227 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4228 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4229 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4230 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4231 g_assert (m->klass->generic_class || m->klass->generic_container);
4232 continue;
4233 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4234 continue;
4235 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4236 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4237 g_assert (is_field_on_inst (f));
4238 continue;
4239 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4240 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4241 continue;
4242 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4243 continue;
4244 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4245 continue;
4246 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4247 continue;
4248 } else {
4249 g_assert_not_reached ();
4251 break;
4252 case MONO_TABLE_METHODSPEC:
4253 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4254 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4255 g_assert (mono_method_signature (m)->generic_param_count);
4256 continue;
4257 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4258 continue;
4259 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4260 continue;
4261 } else {
4262 g_assert_not_reached ();
4264 break;
4265 default:
4266 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4268 target [0] = idx & 0xff;
4269 target [1] = (idx >> 8) & 0xff;
4270 target [2] = (idx >> 16) & 0xff;
4275 * fixup_cattrs:
4277 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4278 * value is not known when the table is emitted.
4280 static void
4281 fixup_cattrs (MonoDynamicImage *assembly)
4283 MonoDynamicTable *table;
4284 guint32 *values;
4285 guint32 type, i, idx, token;
4286 MonoObject *ctor;
4288 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4290 for (i = 0; i < table->rows; ++i) {
4291 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4293 type = values [MONO_CUSTOM_ATTR_TYPE];
4294 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4295 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4296 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4297 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4298 g_assert (ctor);
4300 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4301 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4302 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4303 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4309 static void
4310 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4312 MonoDynamicTable *table;
4313 guint32 *values;
4315 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4316 table->rows++;
4317 alloc_table (table, table->rows);
4318 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4319 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4320 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4321 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4322 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4323 table->next_idx++;
4326 static void
4327 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4329 MonoDynamicTable *table;
4330 guint32 *values;
4331 char blob_size [6];
4332 guchar hash [20];
4333 char *b = blob_size;
4334 char *name, *sname;
4335 guint32 idx, offset;
4337 if (rsrc->filename) {
4338 name = mono_string_to_utf8 (rsrc->filename);
4339 sname = g_path_get_basename (name);
4341 table = &assembly->tables [MONO_TABLE_FILE];
4342 table->rows++;
4343 alloc_table (table, table->rows);
4344 values = table->values + table->next_idx * MONO_FILE_SIZE;
4345 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4346 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4347 g_free (sname);
4349 mono_sha1_get_digest_from_file (name, hash);
4350 mono_metadata_encode_value (20, b, &b);
4351 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4352 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4353 g_free (name);
4354 idx = table->next_idx++;
4355 rsrc->offset = 0;
4356 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4357 } else {
4358 char sizebuf [4];
4359 char *data;
4360 guint len;
4361 if (rsrc->data) {
4362 data = mono_array_addr (rsrc->data, char, 0);
4363 len = mono_array_length (rsrc->data);
4364 } else {
4365 data = NULL;
4366 len = 0;
4368 offset = len;
4369 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4370 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4371 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4372 mono_image_add_stream_data (&assembly->resources, data, len);
4374 if (!mb->is_main)
4376 * The entry should be emitted into the MANIFESTRESOURCE table of
4377 * the main module, but that needs to reference the FILE table
4378 * which isn't emitted yet.
4380 return;
4381 else
4382 idx = 0;
4385 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4388 static void
4389 set_version_from_string (MonoString *version, guint32 *values)
4391 gchar *ver, *p, *str;
4392 guint32 i;
4394 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4395 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4396 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4397 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4398 if (!version)
4399 return;
4400 ver = str = mono_string_to_utf8 (version);
4401 for (i = 0; i < 4; ++i) {
4402 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4403 switch (*p) {
4404 case '.':
4405 p++;
4406 break;
4407 case '*':
4408 /* handle Revision and Build */
4409 p++;
4410 break;
4412 ver = p;
4414 g_free (str);
4417 static guint32
4418 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4419 gsize len;
4420 guint32 token = 0;
4421 char blob_size [6];
4422 char *b = blob_size;
4424 if (!pkey)
4425 return token;
4427 len = mono_array_length (pkey);
4428 mono_metadata_encode_value (len, b, &b);
4429 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4430 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4432 assembly->public_key = g_malloc (len);
4433 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4434 assembly->public_key_len = len;
4436 /* Special case: check for ECMA key (16 bytes) */
4437 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4438 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4439 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4440 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4441 /* minimum key size (in 2.0) is 384 bits */
4442 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4443 } else {
4444 /* FIXME - verifier */
4445 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4446 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4448 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4450 return token;
4453 static void
4454 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4456 MonoDynamicTable *table;
4457 MonoDynamicImage *assembly;
4458 MonoReflectionAssemblyBuilder *assemblyb;
4459 MonoDomain *domain;
4460 guint32 *values;
4461 int i;
4462 guint32 module_index;
4464 assemblyb = moduleb->assemblyb;
4465 assembly = moduleb->dynamic_image;
4466 domain = mono_object_domain (assemblyb);
4468 /* Emit ASSEMBLY table */
4469 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4470 alloc_table (table, 1);
4471 values = table->values + MONO_ASSEMBLY_SIZE;
4472 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4473 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4474 if (assemblyb->culture) {
4475 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4476 } else {
4477 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4479 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4480 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4481 set_version_from_string (assemblyb->version, values);
4483 /* Emit FILE + EXPORTED_TYPE table */
4484 module_index = 0;
4485 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4486 int j;
4487 MonoReflectionModuleBuilder *file_module =
4488 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4489 if (file_module != moduleb) {
4490 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4491 module_index ++;
4492 if (file_module->types) {
4493 for (j = 0; j < file_module->num_types; ++j) {
4494 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4495 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4500 if (assemblyb->loaded_modules) {
4501 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4502 MonoReflectionModule *file_module =
4503 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4504 mono_image_fill_file_table (domain, file_module, assembly);
4505 module_index ++;
4506 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4509 if (assemblyb->type_forwarders)
4510 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4512 /* Emit MANIFESTRESOURCE table */
4513 module_index = 0;
4514 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4515 int j;
4516 MonoReflectionModuleBuilder *file_module =
4517 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4518 /* The table for the main module is emitted later */
4519 if (file_module != moduleb) {
4520 module_index ++;
4521 if (file_module->resources) {
4522 int len = mono_array_length (file_module->resources);
4523 for (j = 0; j < len; ++j) {
4524 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4525 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4532 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4535 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4536 * for the modulebuilder @moduleb.
4537 * At the end of the process, method and field tokens are fixed up and the
4538 * on-disk compressed metadata representation is created.
4540 void
4541 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4543 MonoDynamicTable *table;
4544 MonoDynamicImage *assembly;
4545 MonoReflectionAssemblyBuilder *assemblyb;
4546 MonoDomain *domain;
4547 MonoPtrArray types;
4548 guint32 *values;
4549 int i, j;
4551 assemblyb = moduleb->assemblyb;
4552 assembly = moduleb->dynamic_image;
4553 domain = mono_object_domain (assemblyb);
4555 if (assembly->text_rva)
4556 return;
4558 assembly->text_rva = START_TEXT_RVA;
4560 if (moduleb->is_main) {
4561 mono_image_emit_manifest (moduleb);
4564 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4565 table->rows = 1; /* .<Module> */
4566 table->next_idx++;
4567 alloc_table (table, table->rows);
4569 * Set the first entry.
4571 values = table->values + table->columns;
4572 values [MONO_TYPEDEF_FLAGS] = 0;
4573 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4574 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4575 values [MONO_TYPEDEF_EXTENDS] = 0;
4576 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4577 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4580 * handle global methods
4581 * FIXME: test what to do when global methods are defined in multiple modules.
4583 if (moduleb->global_methods) {
4584 table = &assembly->tables [MONO_TABLE_METHOD];
4585 table->rows += mono_array_length (moduleb->global_methods);
4586 alloc_table (table, table->rows);
4587 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4588 mono_image_get_method_info (
4589 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4591 if (moduleb->global_fields) {
4592 table = &assembly->tables [MONO_TABLE_FIELD];
4593 table->rows += mono_array_length (moduleb->global_fields);
4594 alloc_table (table, table->rows);
4595 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4596 mono_image_get_field_info (
4597 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4600 table = &assembly->tables [MONO_TABLE_MODULE];
4601 alloc_table (table, 1);
4602 mono_image_fill_module_table (domain, moduleb, assembly);
4604 /* Collect all types into a list sorted by their table_idx */
4605 mono_ptr_array_init (types, moduleb->num_types);
4607 if (moduleb->types)
4608 for (i = 0; i < moduleb->num_types; ++i) {
4609 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4610 collect_types (&types, type);
4613 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4614 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4615 table->rows += mono_ptr_array_size (types);
4616 alloc_table (table, table->rows);
4619 * Emit type names + namespaces at one place inside the string heap,
4620 * so load_class_names () needs to touch fewer pages.
4622 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4623 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4624 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4626 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4627 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4628 string_heap_insert_mstring (&assembly->sheap, tb->name);
4631 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4632 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4633 mono_image_get_type_info (domain, type, assembly);
4637 * table->rows is already set above and in mono_image_fill_module_table.
4639 /* add all the custom attributes at the end, once all the indexes are stable */
4640 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4642 /* CAS assembly permissions */
4643 if (assemblyb->permissions_minimum)
4644 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4645 if (assemblyb->permissions_optional)
4646 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4647 if (assemblyb->permissions_refused)
4648 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4650 module_add_cattrs (assembly, moduleb);
4652 /* fixup tokens */
4653 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4655 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4656 * the final tokens and don't need another fixup pass. */
4658 if (moduleb->global_methods) {
4659 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4660 MonoReflectionMethodBuilder *mb = mono_array_get (
4661 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4662 mono_image_add_methodimpl (assembly, mb);
4666 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4667 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4668 if (type->methods) {
4669 for (j = 0; j < type->num_methods; ++j) {
4670 MonoReflectionMethodBuilder *mb = mono_array_get (
4671 type->methods, MonoReflectionMethodBuilder*, j);
4673 mono_image_add_methodimpl (assembly, mb);
4678 mono_ptr_array_destroy (types);
4680 fixup_cattrs (assembly);
4683 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4685 void
4686 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4688 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4691 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4694 typedef struct {
4695 guint32 import_lookup_table;
4696 guint32 timestamp;
4697 guint32 forwarder;
4698 guint32 name_rva;
4699 guint32 import_address_table_rva;
4700 } MonoIDT;
4702 typedef struct {
4703 guint32 name_rva;
4704 guint32 flags;
4705 } MonoILT;
4707 #ifndef DISABLE_REFLECTION_EMIT
4710 * mono_image_insert_string:
4711 * @module: module builder object
4712 * @str: a string
4714 * Insert @str into the user string stream of @module.
4716 guint32
4717 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4719 MonoDynamicImage *assembly;
4720 guint32 idx;
4721 char buf [16];
4722 char *b = buf;
4724 MONO_ARCH_SAVE_REGS;
4726 if (!module->dynamic_image)
4727 mono_image_module_basic_init (module);
4729 assembly = module->dynamic_image;
4731 if (assembly->save) {
4732 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4733 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4734 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4736 char *swapped = g_malloc (2 * mono_string_length (str));
4737 const char *p = (const char*)mono_string_chars (str);
4739 swap_with_size (swapped, p, 2, mono_string_length (str));
4740 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4741 g_free (swapped);
4743 #else
4744 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4745 #endif
4746 mono_image_add_stream_data (&assembly->us, "", 1);
4747 } else {
4748 idx = assembly->us.index ++;
4751 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4753 return MONO_TOKEN_STRING | idx;
4756 guint32
4757 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4759 MonoClass *klass;
4760 guint32 token = 0;
4761 MonoMethodSignature *sig;
4763 klass = obj->vtable->klass;
4764 if (strcmp (klass->name, "MonoMethod") == 0) {
4765 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4766 MonoMethodSignature *old;
4767 guint32 sig_token, parent;
4768 int nargs, i;
4770 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4772 nargs = mono_array_length (opt_param_types);
4773 old = mono_method_signature (method);
4774 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4776 sig->hasthis = old->hasthis;
4777 sig->explicit_this = old->explicit_this;
4778 sig->call_convention = old->call_convention;
4779 sig->generic_param_count = old->generic_param_count;
4780 sig->param_count = old->param_count + nargs;
4781 sig->sentinelpos = old->param_count;
4782 sig->ret = old->ret;
4784 for (i = 0; i < old->param_count; i++)
4785 sig->params [i] = old->params [i];
4787 for (i = 0; i < nargs; i++) {
4788 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4789 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4792 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4793 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4794 parent >>= MONO_TYPEDEFORREF_BITS;
4796 parent <<= MONO_MEMBERREF_PARENT_BITS;
4797 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4799 sig_token = method_encode_signature (assembly, sig);
4800 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4801 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4802 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4803 ReflectionMethodBuilder rmb;
4804 guint32 parent, sig_token;
4805 int nopt_args, nparams, ngparams, i;
4806 char *name;
4808 reflection_methodbuilder_from_method_builder (&rmb, mb);
4809 rmb.opt_types = opt_param_types;
4810 nopt_args = mono_array_length (opt_param_types);
4812 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4813 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4814 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4816 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4817 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4818 sig->call_convention = rmb.call_conv;
4819 sig->generic_param_count = ngparams;
4820 sig->param_count = nparams + nopt_args;
4821 sig->sentinelpos = nparams;
4822 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4824 for (i = 0; i < nparams; i++) {
4825 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4826 sig->params [i] = mono_reflection_type_get_handle (rt);
4829 for (i = 0; i < nopt_args; i++) {
4830 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4831 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4834 sig_token = method_builder_encode_signature (assembly, &rmb);
4836 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4837 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4839 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4840 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4842 name = mono_string_to_utf8 (rmb.name);
4843 token = mono_image_get_varargs_method_token (
4844 assembly, parent, name, sig_token);
4845 g_free (name);
4846 } else {
4847 g_error ("requested method token for %s\n", klass->name);
4850 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4851 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4852 return token;
4856 * mono_image_create_token:
4857 * @assembly: a dynamic assembly
4858 * @obj:
4859 * @register_token: Whenever to register the token in the assembly->tokens hash.
4861 * Get a token to insert in the IL code stream for the given MemberInfo.
4862 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4863 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4864 * entry.
4866 guint32
4867 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4868 gboolean create_methodspec, gboolean register_token)
4870 MonoClass *klass;
4871 guint32 token = 0;
4873 klass = obj->vtable->klass;
4875 /* Check for user defined reflection objects */
4876 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4877 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4878 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4880 if (strcmp (klass->name, "MethodBuilder") == 0) {
4881 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4882 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4884 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4885 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4886 else
4887 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4888 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4889 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4890 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4891 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4893 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4894 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4895 else
4896 token = mono_image_get_ctorbuilder_token (assembly, mb);
4897 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4898 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4899 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4900 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4901 if (tb->generic_params) {
4902 token = mono_image_get_generic_field_token (assembly, fb);
4903 } else {
4904 if ((tb->module->dynamic_image == assembly)) {
4905 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4906 } else {
4907 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4910 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4911 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4912 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4913 } else if (strcmp (klass->name, "MonoType") == 0) {
4914 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4915 MonoClass *mc = mono_class_from_mono_type (type);
4916 if (!mono_class_init (mc))
4917 mono_raise_exception (mono_class_get_exception_for_failure (mc));
4919 token = mono_metadata_token_from_dor (
4920 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL));
4921 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4922 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4923 token = mono_metadata_token_from_dor (
4924 mono_image_typedef_or_ref (assembly, type));
4925 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4926 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4927 token = mono_metadata_token_from_dor (
4928 mono_image_typedef_or_ref (assembly, type));
4929 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4930 strcmp (klass->name, "MonoMethod") == 0 ||
4931 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4932 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4933 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4934 if (m->method->is_inflated) {
4935 if (create_methodspec)
4936 token = mono_image_get_methodspec_token (assembly, m->method);
4937 else
4938 token = mono_image_get_inflated_method_token (assembly, m->method);
4939 } else if ((m->method->klass->image == &assembly->image) &&
4940 !m->method->klass->generic_class) {
4941 static guint32 method_table_idx = 0xffffff;
4942 if (m->method->klass->wastypebuilder) {
4943 /* we use the same token as the one that was assigned
4944 * to the Methodbuilder.
4945 * FIXME: do the equivalent for Fields.
4947 token = m->method->token;
4948 } else {
4950 * Each token should have a unique index, but the indexes are
4951 * assigned by managed code, so we don't know about them. An
4952 * easy solution is to count backwards...
4954 method_table_idx --;
4955 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4957 } else {
4958 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4960 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4961 } else if (strcmp (klass->name, "MonoField") == 0) {
4962 MonoReflectionField *f = (MonoReflectionField *)obj;
4963 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4964 static guint32 field_table_idx = 0xffffff;
4965 field_table_idx --;
4966 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4967 } else {
4968 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
4970 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4971 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4972 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4973 token = mono_image_get_array_token (assembly, m);
4974 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4975 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4976 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4977 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4978 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4979 token = mono_metadata_token_from_dor (
4980 mono_image_typedef_or_ref (assembly, type));
4981 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4982 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4983 token = mono_image_get_field_on_inst_token (assembly, f);
4984 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4985 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4986 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4987 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4988 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4989 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4990 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
4991 MonoReflectionType *type = (MonoReflectionType *)obj;
4992 token = mono_metadata_token_from_dor (
4993 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
4994 } else {
4995 g_error ("requested token for %s\n", klass->name);
4998 if (register_token)
4999 mono_image_register_token (assembly, token, obj);
5001 return token;
5005 * mono_image_register_token:
5007 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5008 * the Module.ResolveXXXToken () methods to work.
5010 void
5011 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5013 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5014 if (prev) {
5015 /* There could be multiple MethodInfo objects with the same token */
5016 //g_assert (prev == obj);
5017 } else {
5018 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5022 static MonoDynamicImage*
5023 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5025 static const guchar entrycode [16] = {0xff, 0x25, 0};
5026 MonoDynamicImage *image;
5027 int i;
5029 const char *version;
5031 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5032 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5033 else
5034 version = mono_get_runtime_info ()->runtime_version;
5036 #if HAVE_BOEHM_GC
5037 /* The MonoGHashTable's need GC tracking */
5038 image = GC_MALLOC (sizeof (MonoDynamicImage));
5039 #else
5040 image = g_new0 (MonoDynamicImage, 1);
5041 #endif
5043 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5045 /*g_print ("created image %p\n", image);*/
5046 /* keep in sync with image.c */
5047 image->image.name = assembly_name;
5048 image->image.assembly_name = image->image.name; /* they may be different */
5049 image->image.module_name = module_name;
5050 image->image.version = g_strdup (version);
5051 image->image.md_version_major = 1;
5052 image->image.md_version_minor = 1;
5053 image->image.dynamic = TRUE;
5055 image->image.references = g_new0 (MonoAssembly*, 1);
5056 image->image.references [0] = NULL;
5058 mono_image_init (&image->image);
5060 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5061 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5062 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5063 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5064 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5065 image->handleref = g_hash_table_new (NULL, NULL);
5066 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5067 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5068 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5069 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5070 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5071 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5072 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5073 image->gen_params = g_ptr_array_new ();
5075 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5076 string_heap_init (&image->sheap);
5077 mono_image_add_stream_data (&image->us, "", 1);
5078 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5079 /* import tables... */
5080 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5081 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5082 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5083 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5084 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5085 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5086 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5087 stream_data_align (&image->code);
5089 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5091 for (i=0; i < MONO_TABLE_NUM; ++i) {
5092 image->tables [i].next_idx = 1;
5093 image->tables [i].columns = table_sizes [i];
5096 image->image.assembly = (MonoAssembly*)assembly;
5097 image->run = assembly->run;
5098 image->save = assembly->save;
5099 image->pe_kind = 0x1; /* ILOnly */
5100 image->machine = 0x14c; /* I386 */
5102 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5104 return image;
5106 #endif
5108 static void
5109 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5111 g_free (key);
5114 void
5115 mono_dynamic_image_free (MonoDynamicImage *image)
5117 MonoDynamicImage *di = image;
5118 GList *list;
5119 int i;
5121 if (di->methodspec)
5122 mono_g_hash_table_destroy (di->methodspec);
5123 if (di->typespec)
5124 g_hash_table_destroy (di->typespec);
5125 if (di->typeref)
5126 g_hash_table_destroy (di->typeref);
5127 if (di->handleref)
5128 g_hash_table_destroy (di->handleref);
5129 if (di->handleref_managed)
5130 mono_g_hash_table_destroy (di->handleref_managed);
5131 if (di->tokens)
5132 mono_g_hash_table_destroy (di->tokens);
5133 if (di->generic_def_objects)
5134 mono_g_hash_table_destroy (di->generic_def_objects);
5135 if (di->blob_cache) {
5136 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5137 g_hash_table_destroy (di->blob_cache);
5139 if (di->standalonesig_cache)
5140 g_hash_table_destroy (di->standalonesig_cache);
5141 for (list = di->array_methods; list; list = list->next) {
5142 ArrayMethod *am = (ArrayMethod *)list->data;
5143 g_free (am->sig);
5144 g_free (am->name);
5145 g_free (am);
5147 g_list_free (di->array_methods);
5148 if (di->gen_params) {
5149 for (i = 0; i < di->gen_params->len; i++) {
5150 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5151 if (entry->gparam->type.type) {
5152 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
5153 g_free ((char*)mono_generic_param_info (param)->name);
5154 g_free (param);
5156 mono_gc_deregister_root ((char*) &entry->gparam);
5157 g_free (entry);
5159 g_ptr_array_free (di->gen_params, TRUE);
5161 if (di->token_fixups)
5162 mono_g_hash_table_destroy (di->token_fixups);
5163 if (di->method_to_table_idx)
5164 g_hash_table_destroy (di->method_to_table_idx);
5165 if (di->field_to_table_idx)
5166 g_hash_table_destroy (di->field_to_table_idx);
5167 if (di->method_aux_hash)
5168 g_hash_table_destroy (di->method_aux_hash);
5169 if (di->vararg_aux_hash)
5170 g_hash_table_destroy (di->vararg_aux_hash);
5171 g_free (di->strong_name);
5172 g_free (di->win32_res);
5173 if (di->public_key)
5174 g_free (di->public_key);
5176 /*g_print ("string heap destroy for image %p\n", di);*/
5177 mono_dynamic_stream_reset (&di->sheap);
5178 mono_dynamic_stream_reset (&di->code);
5179 mono_dynamic_stream_reset (&di->resources);
5180 mono_dynamic_stream_reset (&di->us);
5181 mono_dynamic_stream_reset (&di->blob);
5182 mono_dynamic_stream_reset (&di->tstream);
5183 mono_dynamic_stream_reset (&di->guid);
5184 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5185 g_free (di->tables [i].values);
5189 #ifndef DISABLE_REFLECTION_EMIT
5192 * mono_image_basic_init:
5193 * @assembly: an assembly builder object
5195 * Create the MonoImage that represents the assembly builder and setup some
5196 * of the helper hash table and the basic metadata streams.
5198 void
5199 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5201 MonoDynamicAssembly *assembly;
5202 MonoDynamicImage *image;
5203 MonoDomain *domain = mono_object_domain (assemblyb);
5205 MONO_ARCH_SAVE_REGS;
5207 if (assemblyb->dynamic_assembly)
5208 return;
5210 #if HAVE_BOEHM_GC
5211 /* assembly->assembly.image might be GC allocated */
5212 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5213 #else
5214 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5215 #endif
5217 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5219 assembly->assembly.ref_count = 1;
5220 assembly->assembly.dynamic = TRUE;
5221 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5222 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5223 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5224 if (assemblyb->culture)
5225 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5226 else
5227 assembly->assembly.aname.culture = g_strdup ("");
5229 if (assemblyb->version) {
5230 char *vstr = mono_string_to_utf8 (assemblyb->version);
5231 char **version = g_strsplit (vstr, ".", 4);
5232 char **parts = version;
5233 assembly->assembly.aname.major = atoi (*parts++);
5234 assembly->assembly.aname.minor = atoi (*parts++);
5235 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5236 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5238 g_strfreev (version);
5239 g_free (vstr);
5240 } else {
5241 assembly->assembly.aname.major = 0;
5242 assembly->assembly.aname.minor = 0;
5243 assembly->assembly.aname.build = 0;
5244 assembly->assembly.aname.revision = 0;
5247 assembly->run = assemblyb->access != 2;
5248 assembly->save = assemblyb->access != 1;
5249 assembly->domain = domain;
5251 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5252 image->initial_image = TRUE;
5253 assembly->assembly.aname.name = image->image.name;
5254 assembly->assembly.image = &image->image;
5255 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5256 /* -1 to correct for the trailing NULL byte */
5257 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5258 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5260 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5263 mono_domain_assemblies_lock (domain);
5264 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5265 mono_domain_assemblies_unlock (domain);
5267 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5269 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5271 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5274 #endif /* !DISABLE_REFLECTION_EMIT */
5276 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5278 static int
5279 calc_section_size (MonoDynamicImage *assembly)
5281 int nsections = 0;
5283 /* alignment constraints */
5284 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5285 g_assert ((assembly->code.index % 4) == 0);
5286 assembly->meta_size += 3;
5287 assembly->meta_size &= ~3;
5288 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5289 g_assert ((assembly->resources.index % 4) == 0);
5291 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5292 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5293 nsections++;
5295 if (assembly->win32_res) {
5296 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5298 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5299 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5300 nsections++;
5303 assembly->sections [MONO_SECTION_RELOC].size = 12;
5304 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5305 nsections++;
5307 return nsections;
5310 typedef struct {
5311 guint32 id;
5312 guint32 offset;
5313 GSList *children;
5314 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5315 } ResTreeNode;
5317 static int
5318 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5320 ResTreeNode *t1 = (ResTreeNode*)a;
5321 ResTreeNode *t2 = (ResTreeNode*)b;
5323 return t1->id - t2->id;
5327 * resource_tree_create:
5329 * Organize the resources into a resource tree.
5331 static ResTreeNode *
5332 resource_tree_create (MonoArray *win32_resources)
5334 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5335 GSList *l;
5336 int i;
5338 tree = g_new0 (ResTreeNode, 1);
5340 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5341 MonoReflectionWin32Resource *win32_res =
5342 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5344 /* Create node */
5346 /* FIXME: BUG: this stores managed references in unmanaged memory */
5347 lang_node = g_new0 (ResTreeNode, 1);
5348 lang_node->id = win32_res->lang_id;
5349 lang_node->win32_res = win32_res;
5351 /* Create type node if neccesary */
5352 type_node = NULL;
5353 for (l = tree->children; l; l = l->next)
5354 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5355 type_node = (ResTreeNode*)l->data;
5356 break;
5359 if (!type_node) {
5360 type_node = g_new0 (ResTreeNode, 1);
5361 type_node->id = win32_res->res_type;
5364 * The resource types have to be sorted otherwise
5365 * Windows Explorer can't display the version information.
5367 tree->children = g_slist_insert_sorted (tree->children,
5368 type_node, resource_tree_compare_by_id);
5371 /* Create res node if neccesary */
5372 res_node = NULL;
5373 for (l = type_node->children; l; l = l->next)
5374 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5375 res_node = (ResTreeNode*)l->data;
5376 break;
5379 if (!res_node) {
5380 res_node = g_new0 (ResTreeNode, 1);
5381 res_node->id = win32_res->res_id;
5382 type_node->children = g_slist_append (type_node->children, res_node);
5385 res_node->children = g_slist_append (res_node->children, lang_node);
5388 return tree;
5392 * resource_tree_encode:
5394 * Encode the resource tree into the format used in the PE file.
5396 static void
5397 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5399 char *entries;
5400 MonoPEResourceDir dir;
5401 MonoPEResourceDirEntry dir_entry;
5402 MonoPEResourceDataEntry data_entry;
5403 GSList *l;
5404 guint32 res_id_entries;
5407 * For the format of the resource directory, see the article
5408 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5409 * Matt Pietrek
5412 memset (&dir, 0, sizeof (dir));
5413 memset (&dir_entry, 0, sizeof (dir_entry));
5414 memset (&data_entry, 0, sizeof (data_entry));
5416 g_assert (sizeof (dir) == 16);
5417 g_assert (sizeof (dir_entry) == 8);
5418 g_assert (sizeof (data_entry) == 16);
5420 node->offset = p - begin;
5422 /* IMAGE_RESOURCE_DIRECTORY */
5423 res_id_entries = g_slist_length (node->children);
5424 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5426 memcpy (p, &dir, sizeof (dir));
5427 p += sizeof (dir);
5429 /* Reserve space for entries */
5430 entries = p;
5431 p += sizeof (dir_entry) * res_id_entries;
5433 /* Write children */
5434 for (l = node->children; l; l = l->next) {
5435 ResTreeNode *child = (ResTreeNode*)l->data;
5437 if (child->win32_res) {
5438 guint32 size;
5440 child->offset = p - begin;
5442 /* IMAGE_RESOURCE_DATA_ENTRY */
5443 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5444 size = mono_array_length (child->win32_res->res_data);
5445 data_entry.rde_size = GUINT32_TO_LE (size);
5447 memcpy (p, &data_entry, sizeof (data_entry));
5448 p += sizeof (data_entry);
5450 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5451 p += size;
5452 } else {
5453 resource_tree_encode (child, begin, p, &p);
5457 /* IMAGE_RESOURCE_ENTRY */
5458 for (l = node->children; l; l = l->next) {
5459 ResTreeNode *child = (ResTreeNode*)l->data;
5461 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5462 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5464 memcpy (entries, &dir_entry, sizeof (dir_entry));
5465 entries += sizeof (dir_entry);
5468 *endbuf = p;
5471 static void
5472 resource_tree_free (ResTreeNode * node)
5474 GSList * list;
5475 for (list = node->children; list; list = list->next)
5476 resource_tree_free ((ResTreeNode*)list->data);
5477 g_slist_free(node->children);
5478 g_free (node);
5481 static void
5482 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5484 char *buf;
5485 char *p;
5486 guint32 size, i;
5487 MonoReflectionWin32Resource *win32_res;
5488 ResTreeNode *tree;
5490 if (!assemblyb->win32_resources)
5491 return;
5494 * Resources are stored in a three level tree inside the PE file.
5495 * - level one contains a node for each type of resource
5496 * - level two contains a node for each resource
5497 * - level three contains a node for each instance of a resource for a
5498 * specific language.
5501 tree = resource_tree_create (assemblyb->win32_resources);
5503 /* Estimate the size of the encoded tree */
5504 size = 0;
5505 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5506 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5507 size += mono_array_length (win32_res->res_data);
5509 /* Directory structure */
5510 size += mono_array_length (assemblyb->win32_resources) * 256;
5511 p = buf = g_malloc (size);
5513 resource_tree_encode (tree, p, p, &p);
5515 g_assert (p - buf <= size);
5517 assembly->win32_res = g_malloc (p - buf);
5518 assembly->win32_res_size = p - buf;
5519 memcpy (assembly->win32_res, buf, p - buf);
5521 g_free (buf);
5522 resource_tree_free (tree);
5525 static void
5526 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5528 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5529 int i;
5531 p += sizeof (MonoPEResourceDir);
5532 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5533 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5534 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5535 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5536 fixup_resource_directory (res_section, child, rva);
5537 } else {
5538 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5539 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5542 p += sizeof (MonoPEResourceDirEntry);
5546 static void
5547 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5549 guint32 dummy;
5550 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5551 g_error ("WriteFile returned %d\n", GetLastError ());
5555 * mono_image_create_pefile:
5556 * @mb: a module builder object
5558 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5559 * assembly->pefile where it can be easily retrieved later in chunks.
5561 void
5562 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5564 MonoMSDOSHeader *msdos;
5565 MonoDotNetHeader *header;
5566 MonoSectionTable *section;
5567 MonoCLIHeader *cli_header;
5568 guint32 size, image_size, virtual_base, text_offset;
5569 guint32 header_start, section_start, file_offset, virtual_offset;
5570 MonoDynamicImage *assembly;
5571 MonoReflectionAssemblyBuilder *assemblyb;
5572 MonoDynamicStream pefile_stream = {0};
5573 MonoDynamicStream *pefile = &pefile_stream;
5574 int i, nsections;
5575 guint32 *rva, value;
5576 guchar *p;
5577 static const unsigned char msheader[] = {
5578 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5579 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5582 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5583 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5584 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5585 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5588 assemblyb = mb->assemblyb;
5590 mono_image_basic_init (assemblyb);
5591 assembly = mb->dynamic_image;
5593 assembly->pe_kind = assemblyb->pe_kind;
5594 assembly->machine = assemblyb->machine;
5595 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5596 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5598 mono_image_build_metadata (mb);
5600 if (mb->is_main && assemblyb->resources) {
5601 int len = mono_array_length (assemblyb->resources);
5602 for (i = 0; i < len; ++i)
5603 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5606 if (mb->resources) {
5607 int len = mono_array_length (mb->resources);
5608 for (i = 0; i < len; ++i)
5609 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5612 build_compressed_metadata (assembly);
5614 if (mb->is_main)
5615 assembly_add_win32_resources (assembly, assemblyb);
5617 nsections = calc_section_size (assembly);
5619 /* The DOS header and stub */
5620 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5621 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5623 /* the dotnet header */
5624 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5626 /* the section tables */
5627 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5629 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5630 virtual_offset = VIRT_ALIGN;
5631 image_size = 0;
5633 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5634 if (!assembly->sections [i].size)
5635 continue;
5636 /* align offsets */
5637 file_offset += FILE_ALIGN - 1;
5638 file_offset &= ~(FILE_ALIGN - 1);
5639 virtual_offset += VIRT_ALIGN - 1;
5640 virtual_offset &= ~(VIRT_ALIGN - 1);
5642 assembly->sections [i].offset = file_offset;
5643 assembly->sections [i].rva = virtual_offset;
5645 file_offset += assembly->sections [i].size;
5646 virtual_offset += assembly->sections [i].size;
5647 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5650 file_offset += FILE_ALIGN - 1;
5651 file_offset &= ~(FILE_ALIGN - 1);
5653 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5655 /* back-patch info */
5656 msdos = (MonoMSDOSHeader*)pefile->data;
5657 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5659 header = (MonoDotNetHeader*)(pefile->data + header_start);
5660 header->pesig [0] = 'P';
5661 header->pesig [1] = 'E';
5663 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5664 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5665 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5666 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5667 if (assemblyb->pekind == 1) {
5668 /* it's a dll */
5669 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5670 } else {
5671 /* it's an exe */
5672 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5675 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5677 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5678 header->pe.pe_major = 6;
5679 header->pe.pe_minor = 0;
5680 size = assembly->sections [MONO_SECTION_TEXT].size;
5681 size += FILE_ALIGN - 1;
5682 size &= ~(FILE_ALIGN - 1);
5683 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5684 size = assembly->sections [MONO_SECTION_RSRC].size;
5685 size += FILE_ALIGN - 1;
5686 size &= ~(FILE_ALIGN - 1);
5687 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5688 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5689 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5690 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5691 /* pe_rva_entry_point always at the beginning of the text section */
5692 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5694 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5695 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5696 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5697 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5698 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5699 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5700 size = section_start;
5701 size += FILE_ALIGN - 1;
5702 size &= ~(FILE_ALIGN - 1);
5703 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5704 size = image_size;
5705 size += VIRT_ALIGN - 1;
5706 size &= ~(VIRT_ALIGN - 1);
5707 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5710 // Translate the PEFileKind value to the value expected by the Windows loader
5713 short kind;
5716 // PEFileKinds.Dll == 1
5717 // PEFileKinds.ConsoleApplication == 2
5718 // PEFileKinds.WindowApplication == 3
5720 // need to get:
5721 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5722 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5724 if (assemblyb->pekind == 3)
5725 kind = 2;
5726 else
5727 kind = 3;
5729 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5731 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5732 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5733 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5734 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5735 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5736 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5738 /* fill data directory entries */
5740 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5741 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5743 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5744 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5746 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5747 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5748 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5749 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5750 /* patch entrypoint name */
5751 if (assemblyb->pekind == 1)
5752 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5753 else
5754 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5755 /* patch imported function RVA name */
5756 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5757 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5759 /* the import table */
5760 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5761 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5762 /* patch imported dll RVA name and other entries in the dir */
5763 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5764 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5765 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5766 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5767 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5768 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5770 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5771 value = (assembly->text_rva + assembly->imp_names_offset);
5772 *p++ = (value) & 0xff;
5773 *p++ = (value >> 8) & (0xff);
5774 *p++ = (value >> 16) & (0xff);
5775 *p++ = (value >> 24) & (0xff);
5777 /* the CLI header info */
5778 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5779 cli_header->ch_size = GUINT32_FROM_LE (72);
5780 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5781 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5782 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5783 if (assemblyb->entry_point) {
5784 guint32 table_idx = 0;
5785 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5786 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5787 table_idx = methodb->table_idx;
5788 } else {
5789 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5791 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5792 } else {
5793 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5795 /* The embedded managed resources */
5796 text_offset = assembly->text_rva + assembly->code.index;
5797 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5798 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5799 text_offset += assembly->resources.index;
5800 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5801 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5802 text_offset += assembly->meta_size;
5803 if (assembly->strong_name_size) {
5804 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5805 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5806 text_offset += assembly->strong_name_size;
5809 /* write the section tables and section content */
5810 section = (MonoSectionTable*)(pefile->data + section_start);
5811 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5812 static const char section_names [][7] = {
5813 ".text", ".rsrc", ".reloc"
5815 if (!assembly->sections [i].size)
5816 continue;
5817 strcpy (section->st_name, section_names [i]);
5818 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5819 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5820 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5821 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5822 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5823 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5824 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5825 section ++;
5828 checked_write_file (file, pefile->data, pefile->index);
5830 mono_dynamic_stream_reset (pefile);
5832 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5833 if (!assembly->sections [i].size)
5834 continue;
5836 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5837 g_error ("SetFilePointer returned %d\n", GetLastError ());
5839 switch (i) {
5840 case MONO_SECTION_TEXT:
5841 /* patch entry point */
5842 p = (guchar*)(assembly->code.data + 2);
5843 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5844 *p++ = (value) & 0xff;
5845 *p++ = (value >> 8) & 0xff;
5846 *p++ = (value >> 16) & 0xff;
5847 *p++ = (value >> 24) & 0xff;
5849 checked_write_file (file, assembly->code.data, assembly->code.index);
5850 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5851 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5852 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5855 g_free (assembly->image.raw_metadata);
5856 break;
5857 case MONO_SECTION_RELOC: {
5858 struct {
5859 guint32 page_rva;
5860 guint32 block_size;
5861 guint16 type_and_offset;
5862 guint16 term;
5863 } reloc;
5865 g_assert (sizeof (reloc) == 12);
5867 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5868 reloc.block_size = GUINT32_FROM_LE (12);
5871 * the entrypoint is always at the start of the text section
5872 * 3 is IMAGE_REL_BASED_HIGHLOW
5873 * 2 is patch_size_rva - text_rva
5875 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5876 reloc.term = 0;
5878 checked_write_file (file, &reloc, sizeof (reloc));
5880 break;
5882 case MONO_SECTION_RSRC:
5883 if (assembly->win32_res) {
5885 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5886 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5887 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5889 break;
5890 default:
5891 g_assert_not_reached ();
5895 /* check that the file is properly padded */
5896 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5897 g_error ("SetFilePointer returned %d\n", GetLastError ());
5898 if (! SetEndOfFile (file))
5899 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5901 mono_dynamic_stream_reset (&assembly->code);
5902 mono_dynamic_stream_reset (&assembly->us);
5903 mono_dynamic_stream_reset (&assembly->blob);
5904 mono_dynamic_stream_reset (&assembly->guid);
5905 mono_dynamic_stream_reset (&assembly->sheap);
5907 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5908 g_hash_table_destroy (assembly->blob_cache);
5909 assembly->blob_cache = NULL;
5912 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5914 void
5915 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5917 g_assert_not_reached ();
5920 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5922 #ifndef DISABLE_REFLECTION_EMIT
5924 MonoReflectionModule *
5925 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5927 char *name;
5928 MonoImage *image;
5929 MonoImageOpenStatus status;
5930 MonoDynamicAssembly *assembly;
5931 guint32 module_count;
5932 MonoImage **new_modules;
5933 gboolean *new_modules_loaded;
5935 name = mono_string_to_utf8 (fileName);
5937 image = mono_image_open (name, &status);
5938 if (!image) {
5939 MonoException *exc;
5940 if (status == MONO_IMAGE_ERROR_ERRNO)
5941 exc = mono_get_exception_file_not_found (fileName);
5942 else
5943 exc = mono_get_exception_bad_image_format (name);
5944 g_free (name);
5945 mono_raise_exception (exc);
5948 g_free (name);
5950 assembly = ab->dynamic_assembly;
5951 image->assembly = (MonoAssembly*)assembly;
5953 module_count = image->assembly->image->module_count;
5954 new_modules = g_new0 (MonoImage *, module_count + 1);
5955 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5957 if (image->assembly->image->modules)
5958 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5959 if (image->assembly->image->modules_loaded)
5960 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5961 new_modules [module_count] = image;
5962 new_modules_loaded [module_count] = TRUE;
5963 mono_image_addref (image);
5965 g_free (image->assembly->image->modules);
5966 image->assembly->image->modules = new_modules;
5967 image->assembly->image->modules_loaded = new_modules_loaded;
5968 image->assembly->image->module_count ++;
5970 mono_assembly_load_references (image, &status);
5971 if (status) {
5972 mono_image_close (image);
5973 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5976 return mono_module_get_object (mono_domain_get (), image);
5979 #endif /* DISABLE_REFLECTION_EMIT */
5982 * We need to return always the same object for MethodInfo, FieldInfo etc..
5983 * but we need to consider the reflected type.
5984 * type uses a different hash, since it uses custom hash/equal functions.
5987 typedef struct {
5988 gpointer item;
5989 MonoClass *refclass;
5990 } ReflectedEntry;
5992 static gboolean
5993 reflected_equal (gconstpointer a, gconstpointer b) {
5994 const ReflectedEntry *ea = a;
5995 const ReflectedEntry *eb = b;
5997 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6000 static guint
6001 reflected_hash (gconstpointer a) {
6002 const ReflectedEntry *ea = a;
6003 return mono_aligned_addr_hash (ea->item);
6006 #define CHECK_OBJECT(t,p,k) \
6007 do { \
6008 t _obj; \
6009 ReflectedEntry e; \
6010 e.item = (p); \
6011 e.refclass = (k); \
6012 mono_domain_lock (domain); \
6013 if (!domain->refobject_hash) \
6014 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6015 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6016 mono_domain_unlock (domain); \
6017 return _obj; \
6019 mono_domain_unlock (domain); \
6020 } while (0)
6022 #ifdef HAVE_BOEHM_GC
6023 /* ReflectedEntry doesn't need to be GC tracked */
6024 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6025 #define FREE_REFENTRY(entry) g_free ((entry))
6026 #define REFENTRY_REQUIRES_CLEANUP
6027 #else
6028 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6029 /* FIXME: */
6030 #define FREE_REFENTRY(entry)
6031 #endif
6033 #define CACHE_OBJECT(t,p,o,k) \
6034 do { \
6035 t _obj; \
6036 ReflectedEntry pe; \
6037 pe.item = (p); \
6038 pe.refclass = (k); \
6039 mono_domain_lock (domain); \
6040 if (!domain->refobject_hash) \
6041 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6042 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6043 if (!_obj) { \
6044 ReflectedEntry *e = ALLOC_REFENTRY; \
6045 e->item = (p); \
6046 e->refclass = (k); \
6047 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6048 _obj = o; \
6050 mono_domain_unlock (domain); \
6051 return _obj; \
6052 } while (0)
6054 static void
6055 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6057 mono_domain_lock (domain);
6058 if (domain->refobject_hash) {
6059 ReflectedEntry pe;
6060 gpointer orig_pe, orig_value;
6062 pe.item = o;
6063 pe.refclass = klass;
6064 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6065 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6066 FREE_REFENTRY (orig_pe);
6069 mono_domain_unlock (domain);
6072 #ifdef REFENTRY_REQUIRES_CLEANUP
6073 static void
6074 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6076 FREE_REFENTRY (key);
6078 #endif
6080 void
6081 mono_reflection_cleanup_domain (MonoDomain *domain)
6083 if (domain->refobject_hash) {
6084 /*let's avoid scanning the whole hashtable if not needed*/
6085 #ifdef REFENTRY_REQUIRES_CLEANUP
6086 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6087 #endif
6088 mono_g_hash_table_destroy (domain->refobject_hash);
6089 domain->refobject_hash = NULL;
6093 #ifndef DISABLE_REFLECTION_EMIT
6094 static gpointer
6095 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6097 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6100 static gpointer
6101 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6103 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6106 void
6107 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6109 MonoDynamicImage *image = moduleb->dynamic_image;
6110 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6111 if (!image) {
6112 MonoError error;
6113 int module_count;
6114 MonoImage **new_modules;
6115 MonoImage *ass;
6116 char *name, *fqname;
6118 * FIXME: we already created an image in mono_image_basic_init (), but
6119 * we don't know which module it belongs to, since that is only
6120 * determined at assembly save time.
6122 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6123 name = mono_string_to_utf8 (ab->name);
6124 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6125 if (!mono_error_ok (&error)) {
6126 g_free (name);
6127 mono_error_raise_exception (&error);
6129 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6131 moduleb->module.image = &image->image;
6132 moduleb->dynamic_image = image;
6133 register_module (mono_object_domain (moduleb), moduleb, image);
6135 /* register the module with the assembly */
6136 ass = ab->dynamic_assembly->assembly.image;
6137 module_count = ass->module_count;
6138 new_modules = g_new0 (MonoImage *, module_count + 1);
6140 if (ass->modules)
6141 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6142 new_modules [module_count] = &image->image;
6143 mono_image_addref (&image->image);
6145 g_free (ass->modules);
6146 ass->modules = new_modules;
6147 ass->module_count ++;
6151 void
6152 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6154 MonoDynamicImage *image = moduleb->dynamic_image;
6156 g_assert (type->type);
6157 image->wrappers_type = mono_class_from_mono_type (type->type);
6160 #endif
6163 * mono_assembly_get_object:
6164 * @domain: an app domain
6165 * @assembly: an assembly
6167 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6169 MonoReflectionAssembly*
6170 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6172 static MonoClass *assembly_type;
6173 MonoReflectionAssembly *res;
6175 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6176 if (!assembly_type) {
6177 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6178 if (class == NULL)
6179 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6180 g_assert (class);
6181 assembly_type = class;
6183 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6184 res->assembly = assembly;
6186 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6191 MonoReflectionModule*
6192 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6194 static MonoClass *module_type;
6195 MonoReflectionModule *res;
6196 char* basename;
6198 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6199 if (!module_type) {
6200 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6201 if (class == NULL)
6202 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6203 g_assert (class);
6204 module_type = class;
6206 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6208 res->image = image;
6209 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6211 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6212 basename = g_path_get_basename (image->name);
6213 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6214 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6216 g_free (basename);
6218 if (image->assembly->image == image) {
6219 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6220 } else {
6221 int i;
6222 res->token = 0;
6223 if (image->assembly->image->modules) {
6224 for (i = 0; i < image->assembly->image->module_count; i++) {
6225 if (image->assembly->image->modules [i] == image)
6226 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6228 g_assert (res->token);
6232 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6235 MonoReflectionModule*
6236 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6238 static MonoClass *module_type;
6239 MonoReflectionModule *res;
6240 MonoTableInfo *table;
6241 guint32 cols [MONO_FILE_SIZE];
6242 const char *name;
6243 guint32 i, name_idx;
6244 const char *val;
6246 if (!module_type) {
6247 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6248 if (class == NULL)
6249 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6250 g_assert (class);
6251 module_type = class;
6253 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6255 table = &image->tables [MONO_TABLE_FILE];
6256 g_assert (table_index < table->rows);
6257 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6259 res->image = NULL;
6260 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6261 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6263 /* Check whenever the row has a corresponding row in the moduleref table */
6264 table = &image->tables [MONO_TABLE_MODULEREF];
6265 for (i = 0; i < table->rows; ++i) {
6266 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6267 val = mono_metadata_string_heap (image, name_idx);
6268 if (strcmp (val, name) == 0)
6269 res->image = image->modules [i];
6272 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6273 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6274 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6275 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6276 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6278 return res;
6281 static gboolean
6282 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6284 if ((t1->type != t2->type) ||
6285 (t1->byref != t2->byref))
6286 return FALSE;
6288 switch (t1->type) {
6289 case MONO_TYPE_VOID:
6290 case MONO_TYPE_BOOLEAN:
6291 case MONO_TYPE_CHAR:
6292 case MONO_TYPE_I1:
6293 case MONO_TYPE_U1:
6294 case MONO_TYPE_I2:
6295 case MONO_TYPE_U2:
6296 case MONO_TYPE_I4:
6297 case MONO_TYPE_U4:
6298 case MONO_TYPE_I8:
6299 case MONO_TYPE_U8:
6300 case MONO_TYPE_R4:
6301 case MONO_TYPE_R8:
6302 case MONO_TYPE_STRING:
6303 case MONO_TYPE_I:
6304 case MONO_TYPE_U:
6305 case MONO_TYPE_OBJECT:
6306 case MONO_TYPE_TYPEDBYREF:
6307 return TRUE;
6308 case MONO_TYPE_VALUETYPE:
6309 case MONO_TYPE_CLASS:
6310 case MONO_TYPE_SZARRAY:
6311 return t1->data.klass == t2->data.klass;
6312 case MONO_TYPE_PTR:
6313 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6314 case MONO_TYPE_ARRAY:
6315 if (t1->data.array->rank != t2->data.array->rank)
6316 return FALSE;
6317 return t1->data.array->eklass == t2->data.array->eklass;
6318 case MONO_TYPE_GENERICINST: {
6319 int i;
6320 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6321 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6322 if (i1->type_argc != i2->type_argc)
6323 return FALSE;
6324 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6325 &t2->data.generic_class->container_class->byval_arg))
6326 return FALSE;
6327 /* FIXME: we should probably just compare the instance pointers directly. */
6328 for (i = 0; i < i1->type_argc; ++i) {
6329 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6330 return FALSE;
6332 return TRUE;
6334 case MONO_TYPE_VAR:
6335 case MONO_TYPE_MVAR:
6336 return t1->data.generic_param == t2->data.generic_param;
6337 default:
6338 g_error ("implement type compare for %0x!", t1->type);
6339 return FALSE;
6342 return FALSE;
6345 static guint
6346 mymono_metadata_type_hash (MonoType *t1)
6348 guint hash;
6350 hash = t1->type;
6352 hash |= t1->byref << 6; /* do not collide with t1->type values */
6353 switch (t1->type) {
6354 case MONO_TYPE_VALUETYPE:
6355 case MONO_TYPE_CLASS:
6356 case MONO_TYPE_SZARRAY:
6357 /* check if the distribution is good enough */
6358 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6359 case MONO_TYPE_PTR:
6360 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6361 case MONO_TYPE_GENERICINST: {
6362 int i;
6363 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6364 hash += g_str_hash (t1->data.generic_class->container_class->name);
6365 hash *= 13;
6366 for (i = 0; i < inst->type_argc; ++i) {
6367 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6368 hash *= 13;
6370 return hash;
6373 return hash;
6376 static gboolean
6377 verify_safe_for_managed_space (MonoType *type)
6379 switch (type->type) {
6380 #ifdef DEBUG_HARDER
6381 case MONO_TYPE_ARRAY:
6382 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6383 case MONO_TYPE_PTR:
6384 return verify_safe_for_managed_space (type->data.type);
6385 case MONO_TYPE_SZARRAY:
6386 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6387 case MONO_TYPE_GENERICINST: {
6388 MonoGenericInst *inst = type->data.generic_class->inst;
6389 int i;
6390 if (!inst->is_open)
6391 break;
6392 for (i = 0; i < inst->type_argc; ++i)
6393 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6394 return FALSE;
6395 break;
6397 #endif
6398 case MONO_TYPE_VAR:
6399 case MONO_TYPE_MVAR:
6400 return TRUE;
6402 return TRUE;
6405 static MonoType*
6406 mono_type_normalize (MonoType *type)
6408 int i;
6409 MonoGenericClass *gclass;
6410 MonoGenericInst *ginst;
6411 MonoClass *gtd;
6412 MonoGenericContainer *gcontainer;
6413 MonoType **argv = NULL;
6414 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6416 if (type->type != MONO_TYPE_GENERICINST)
6417 return type;
6419 gclass = type->data.generic_class;
6420 ginst = gclass->context.class_inst;
6421 if (!ginst->is_open)
6422 return type;
6424 gtd = gclass->container_class;
6425 gcontainer = gtd->generic_container;
6426 argv = g_newa (MonoType*, ginst->type_argc);
6428 for (i = 0; i < ginst->type_argc; ++i) {
6429 MonoType *t = ginst->type_argv [i], *norm;
6430 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6431 is_denorm_gtd = FALSE;
6432 norm = mono_type_normalize (t);
6433 argv [i] = norm;
6434 if (norm != t)
6435 requires_rebind = TRUE;
6438 if (is_denorm_gtd)
6439 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6441 if (requires_rebind) {
6442 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6443 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6446 return type;
6449 * mono_type_get_object:
6450 * @domain: an app domain
6451 * @type: a type
6453 * Return an System.MonoType object representing the type @type.
6455 MonoReflectionType*
6456 mono_type_get_object (MonoDomain *domain, MonoType *type)
6458 MonoType *norm_type;
6459 MonoReflectionType *res;
6460 MonoClass *klass = mono_class_from_mono_type (type);
6462 /*we must avoid using @type as it might have come
6463 * from a mono_metadata_type_dup and the caller
6464 * expects that is can be freed.
6465 * Using the right type from
6467 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6469 /* void is very common */
6470 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6471 return (MonoReflectionType*)domain->typeof_void;
6474 * If the vtable of the given class was already created, we can use
6475 * the MonoType from there and avoid all locking and hash table lookups.
6477 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6478 * that the resulting object is different.
6480 if (type == &klass->byval_arg && !klass->image->dynamic) {
6481 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6482 if (vtable && vtable->type)
6483 return vtable->type;
6486 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6487 mono_domain_lock (domain);
6488 if (!domain->type_hash)
6489 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6490 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6491 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6492 mono_domain_unlock (domain);
6493 mono_loader_unlock ();
6494 return res;
6497 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6498 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6499 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6500 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6501 * artifact of how generics are encoded and should be transparent to managed code so we
6502 * need to weed out this diference when retrieving managed System.Type objects.
6504 norm_type = mono_type_normalize (type);
6505 if (norm_type != type) {
6506 res = mono_type_get_object (domain, norm_type);
6507 mono_g_hash_table_insert (domain->type_hash, type, res);
6508 mono_domain_unlock (domain);
6509 mono_loader_unlock ();
6510 return res;
6513 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6514 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6515 g_assert (0);
6517 if (!verify_safe_for_managed_space (type)) {
6518 mono_domain_unlock (domain);
6519 mono_loader_unlock ();
6520 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6523 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6524 gboolean is_type_done = TRUE;
6525 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6526 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6527 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6529 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6530 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6532 if (gparam->owner && gparam->owner->is_method) {
6533 MonoMethod *method = gparam->owner->owner.method;
6534 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6535 is_type_done = FALSE;
6536 } else if (gparam->owner && !gparam->owner->is_method) {
6537 MonoClass *klass = gparam->owner->owner.klass;
6538 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6539 is_type_done = FALSE;
6543 /* g_assert_not_reached (); */
6544 /* should this be considered an error condition? */
6545 if (is_type_done && !type->byref) {
6546 mono_domain_unlock (domain);
6547 mono_loader_unlock ();
6548 return mono_class_get_ref_info (klass);
6551 #ifdef HAVE_SGEN_GC
6552 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6553 #else
6554 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6555 #endif
6556 res->type = type;
6557 mono_g_hash_table_insert (domain->type_hash, type, res);
6559 if (type->type == MONO_TYPE_VOID)
6560 domain->typeof_void = (MonoObject*)res;
6562 mono_domain_unlock (domain);
6563 mono_loader_unlock ();
6564 return res;
6568 * mono_method_get_object:
6569 * @domain: an app domain
6570 * @method: a method
6571 * @refclass: the reflected type (can be NULL)
6573 * Return an System.Reflection.MonoMethod object representing the method @method.
6575 MonoReflectionMethod*
6576 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6579 * We use the same C representation for methods and constructors, but the type
6580 * name in C# is different.
6582 static MonoClass *System_Reflection_MonoMethod = NULL;
6583 static MonoClass *System_Reflection_MonoCMethod = NULL;
6584 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6585 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6586 MonoClass *klass;
6587 MonoReflectionMethod *ret;
6589 if (method->is_inflated) {
6590 MonoReflectionGenericMethod *gret;
6592 refclass = method->klass;
6593 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6594 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6595 if (!System_Reflection_MonoGenericCMethod)
6596 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6597 klass = System_Reflection_MonoGenericCMethod;
6598 } else {
6599 if (!System_Reflection_MonoGenericMethod)
6600 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6601 klass = System_Reflection_MonoGenericMethod;
6603 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6604 gret->method.method = method;
6605 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6606 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6607 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6610 if (!refclass)
6611 refclass = method->klass;
6613 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6614 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6615 if (!System_Reflection_MonoCMethod)
6616 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6617 klass = System_Reflection_MonoCMethod;
6619 else {
6620 if (!System_Reflection_MonoMethod)
6621 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6622 klass = System_Reflection_MonoMethod;
6624 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6625 ret->method = method;
6626 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6627 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6631 * mono_method_clear_object:
6633 * Clear the cached reflection objects for the dynamic method METHOD.
6635 void
6636 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6638 MonoClass *klass;
6639 g_assert (method->dynamic);
6641 klass = method->klass;
6642 while (klass) {
6643 clear_cached_object (domain, method, klass);
6644 klass = klass->parent;
6646 /* Added by mono_param_get_objects () */
6647 clear_cached_object (domain, &(method->signature), NULL);
6648 klass = method->klass;
6649 while (klass) {
6650 clear_cached_object (domain, &(method->signature), klass);
6651 klass = klass->parent;
6656 * mono_field_get_object:
6657 * @domain: an app domain
6658 * @klass: a type
6659 * @field: a field
6661 * Return an System.Reflection.MonoField object representing the field @field
6662 * in class @klass.
6664 MonoReflectionField*
6665 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6667 MonoReflectionField *res;
6668 static MonoClass *monofield_klass;
6670 CHECK_OBJECT (MonoReflectionField *, field, klass);
6671 if (!monofield_klass)
6672 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6673 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6674 res->klass = klass;
6675 res->field = field;
6676 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6677 if (is_field_on_inst (field))
6678 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6679 else
6680 res->attrs = field->type->attrs;
6681 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6682 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6686 * mono_property_get_object:
6687 * @domain: an app domain
6688 * @klass: a type
6689 * @property: a property
6691 * Return an System.Reflection.MonoProperty object representing the property @property
6692 * in class @klass.
6694 MonoReflectionProperty*
6695 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6697 MonoReflectionProperty *res;
6698 static MonoClass *monoproperty_klass;
6700 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6701 if (!monoproperty_klass)
6702 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6703 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6704 res->klass = klass;
6705 res->property = property;
6706 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6710 * mono_event_get_object:
6711 * @domain: an app domain
6712 * @klass: a type
6713 * @event: a event
6715 * Return an System.Reflection.MonoEvent object representing the event @event
6716 * in class @klass.
6718 MonoReflectionEvent*
6719 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6721 MonoReflectionEvent *res;
6722 MonoReflectionMonoEvent *mono_event;
6723 static MonoClass *monoevent_klass;
6725 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6726 if (!monoevent_klass)
6727 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6728 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6729 mono_event->klass = klass;
6730 mono_event->event = event;
6731 res = (MonoReflectionEvent*)mono_event;
6732 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6736 * mono_get_reflection_missing_object:
6737 * @domain: Domain where the object lives
6739 * Returns the System.Reflection.Missing.Value singleton object
6740 * (of type System.Reflection.Missing).
6742 * Used as the value for ParameterInfo.DefaultValue when Optional
6743 * is present
6745 static MonoObject *
6746 mono_get_reflection_missing_object (MonoDomain *domain)
6748 MonoObject *obj;
6749 static MonoClassField *missing_value_field = NULL;
6751 if (!missing_value_field) {
6752 MonoClass *missing_klass;
6753 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6754 mono_class_init (missing_klass);
6755 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6756 g_assert (missing_value_field);
6758 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6759 g_assert (obj);
6760 return obj;
6763 static MonoObject*
6764 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6766 if (!*dbnull)
6767 *dbnull = mono_get_dbnull_object (domain);
6768 return *dbnull;
6771 static MonoObject*
6772 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6774 if (!*reflection_missing)
6775 *reflection_missing = mono_get_reflection_missing_object (domain);
6776 return *reflection_missing;
6780 * mono_param_get_objects:
6781 * @domain: an app domain
6782 * @method: a method
6784 * Return an System.Reflection.ParameterInfo array object representing the parameters
6785 * in the method @method.
6787 MonoArray*
6788 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6790 static MonoClass *System_Reflection_ParameterInfo;
6791 static MonoClass *System_Reflection_ParameterInfo_array;
6792 MonoArray *res = NULL;
6793 MonoReflectionMethod *member = NULL;
6794 MonoReflectionParameter *param = NULL;
6795 char **names, **blobs = NULL;
6796 guint32 *types = NULL;
6797 MonoType *type = NULL;
6798 MonoObject *dbnull = NULL;
6799 MonoObject *missing = NULL;
6800 MonoMarshalSpec **mspecs;
6801 MonoMethodSignature *sig;
6802 MonoVTable *pinfo_vtable;
6803 int i;
6805 if (!System_Reflection_ParameterInfo_array) {
6806 MonoClass *klass;
6808 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6809 mono_memory_barrier ();
6810 System_Reflection_ParameterInfo = klass;
6812 klass = mono_array_class_get (klass, 1);
6813 mono_memory_barrier ();
6814 System_Reflection_ParameterInfo_array = klass;
6817 if (!mono_method_signature (method)->param_count)
6818 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6820 /* Note: the cache is based on the address of the signature into the method
6821 * since we already cache MethodInfos with the method as keys.
6823 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6825 sig = mono_method_signature (method);
6826 member = mono_method_get_object (domain, method, refclass);
6827 names = g_new (char *, sig->param_count);
6828 mono_method_get_param_names (method, (const char **) names);
6830 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6831 mono_method_get_marshal_info (method, mspecs);
6833 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6834 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6835 for (i = 0; i < sig->param_count; ++i) {
6836 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6837 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6838 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6839 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6840 param->PositionImpl = i;
6841 param->AttrsImpl = sig->params [i]->attrs;
6843 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6844 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6845 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6846 else
6847 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6848 } else {
6850 if (!blobs) {
6851 blobs = g_new0 (char *, sig->param_count);
6852 types = g_new0 (guint32, sig->param_count);
6853 get_default_param_value_blobs (method, blobs, types);
6856 /* Build MonoType for the type from the Constant Table */
6857 if (!type)
6858 type = g_new0 (MonoType, 1);
6859 type->type = types [i];
6860 type->data.klass = NULL;
6861 if (types [i] == MONO_TYPE_CLASS)
6862 type->data.klass = mono_defaults.object_class;
6863 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6864 /* For enums, types [i] contains the base type */
6866 type->type = MONO_TYPE_VALUETYPE;
6867 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6868 } else
6869 type->data.klass = mono_class_from_mono_type (type);
6871 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6873 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6874 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6875 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6876 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6877 else
6878 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6883 if (mspecs [i + 1])
6884 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6886 mono_array_setref (res, i, param);
6888 g_free (names);
6889 g_free (blobs);
6890 g_free (types);
6891 g_free (type);
6893 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6894 if (mspecs [i])
6895 mono_metadata_free_marshal_spec (mspecs [i]);
6896 g_free (mspecs);
6898 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6901 MonoArray*
6902 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6904 return mono_param_get_objects_internal (domain, method, NULL);
6908 * mono_method_body_get_object:
6909 * @domain: an app domain
6910 * @method: a method
6912 * Return an System.Reflection.MethodBody object representing the method @method.
6914 MonoReflectionMethodBody*
6915 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6917 static MonoClass *System_Reflection_MethodBody = NULL;
6918 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6919 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6920 MonoReflectionMethodBody *ret;
6921 MonoMethodHeader *header;
6922 MonoImage *image;
6923 guint32 method_rva, local_var_sig_token;
6924 char *ptr;
6925 unsigned char format, flags;
6926 int i;
6928 if (!System_Reflection_MethodBody)
6929 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6930 if (!System_Reflection_LocalVariableInfo)
6931 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6932 if (!System_Reflection_ExceptionHandlingClause)
6933 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6935 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6937 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6938 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6939 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6940 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6941 return NULL;
6943 image = method->klass->image;
6944 header = mono_method_get_header (method);
6946 if (!image->dynamic) {
6947 /* Obtain local vars signature token */
6948 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6949 ptr = mono_image_rva_map (image, method_rva);
6950 flags = *(const unsigned char *) ptr;
6951 format = flags & METHOD_HEADER_FORMAT_MASK;
6952 switch (format){
6953 case METHOD_HEADER_TINY_FORMAT:
6954 local_var_sig_token = 0;
6955 break;
6956 case METHOD_HEADER_FAT_FORMAT:
6957 ptr += 2;
6958 ptr += 2;
6959 ptr += 4;
6960 local_var_sig_token = read32 (ptr);
6961 break;
6962 default:
6963 g_assert_not_reached ();
6965 } else
6966 local_var_sig_token = 0; //FIXME
6968 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6970 ret->init_locals = header->init_locals;
6971 ret->max_stack = header->max_stack;
6972 ret->local_var_sig_token = local_var_sig_token;
6973 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6974 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6976 /* Locals */
6977 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6978 for (i = 0; i < header->num_locals; ++i) {
6979 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6980 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6981 info->is_pinned = header->locals [i]->pinned;
6982 info->local_index = i;
6983 mono_array_setref (ret->locals, i, info);
6986 /* Exceptions */
6987 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6988 for (i = 0; i < header->num_clauses; ++i) {
6989 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6990 MonoExceptionClause *clause = &header->clauses [i];
6992 info->flags = clause->flags;
6993 info->try_offset = clause->try_offset;
6994 info->try_length = clause->try_len;
6995 info->handler_offset = clause->handler_offset;
6996 info->handler_length = clause->handler_len;
6997 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6998 info->filter_offset = clause->data.filter_offset;
6999 else if (clause->data.catch_class)
7000 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7002 mono_array_setref (ret->clauses, i, info);
7005 mono_metadata_free_mh (header);
7006 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7007 return ret;
7011 * mono_get_dbnull_object:
7012 * @domain: Domain where the object lives
7014 * Returns the System.DBNull.Value singleton object
7016 * Used as the value for ParameterInfo.DefaultValue
7018 MonoObject *
7019 mono_get_dbnull_object (MonoDomain *domain)
7021 MonoObject *obj;
7022 static MonoClassField *dbnull_value_field = NULL;
7024 if (!dbnull_value_field) {
7025 MonoClass *dbnull_klass;
7026 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7027 mono_class_init (dbnull_klass);
7028 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7029 g_assert (dbnull_value_field);
7031 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7032 g_assert (obj);
7033 return obj;
7036 static void
7037 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7039 guint32 param_index, i, lastp, crow = 0;
7040 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7041 gint32 idx;
7043 MonoClass *klass = method->klass;
7044 MonoImage *image = klass->image;
7045 MonoMethodSignature *methodsig = mono_method_signature (method);
7047 MonoTableInfo *constt;
7048 MonoTableInfo *methodt;
7049 MonoTableInfo *paramt;
7051 if (!methodsig->param_count)
7052 return;
7054 mono_class_init (klass);
7056 if (klass->image->dynamic) {
7057 MonoReflectionMethodAux *aux;
7058 if (method->is_inflated)
7059 method = ((MonoMethodInflated*)method)->declaring;
7060 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7061 if (aux && aux->param_defaults) {
7062 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7063 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7065 return;
7068 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7069 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7070 constt = &image->tables [MONO_TABLE_CONSTANT];
7072 idx = mono_method_get_index (method) - 1;
7073 g_assert (idx != -1);
7075 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7076 if (idx + 1 < methodt->rows)
7077 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7078 else
7079 lastp = paramt->rows + 1;
7081 for (i = param_index; i < lastp; ++i) {
7082 guint32 paramseq;
7084 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7085 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7087 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7088 continue;
7090 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7091 if (!crow) {
7092 continue;
7095 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7096 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7097 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7100 return;
7103 MonoObject *
7104 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7106 void *retval;
7107 MonoClass *klass;
7108 MonoObject *object;
7109 MonoType *basetype = type;
7111 if (!blob)
7112 return NULL;
7114 klass = mono_class_from_mono_type (type);
7115 if (klass->valuetype) {
7116 object = mono_object_new (domain, klass);
7117 retval = ((gchar *) object + sizeof (MonoObject));
7118 if (klass->enumtype)
7119 basetype = mono_class_enum_basetype (klass);
7120 } else {
7121 retval = &object;
7124 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7125 return object;
7126 else
7127 return NULL;
7130 static int
7131 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7132 int found_sep;
7133 char *s;
7135 memset (assembly, 0, sizeof (MonoAssemblyName));
7136 assembly->name = p;
7137 assembly->culture = "";
7138 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7140 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
7141 p++;
7142 found_sep = 0;
7143 while (g_ascii_isspace (*p) || *p == ',') {
7144 *p++ = 0;
7145 found_sep = 1;
7146 continue;
7148 /* failed */
7149 if (!found_sep)
7150 return 1;
7151 while (*p) {
7152 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7153 p += 8;
7154 assembly->major = strtoul (p, &s, 10);
7155 if (s == p || *s != '.')
7156 return 1;
7157 p = ++s;
7158 assembly->minor = strtoul (p, &s, 10);
7159 if (s == p || *s != '.')
7160 return 1;
7161 p = ++s;
7162 assembly->build = strtoul (p, &s, 10);
7163 if (s == p || *s != '.')
7164 return 1;
7165 p = ++s;
7166 assembly->revision = strtoul (p, &s, 10);
7167 if (s == p)
7168 return 1;
7169 p = s;
7170 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7171 p += 8;
7172 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7173 assembly->culture = "";
7174 p += 7;
7175 } else {
7176 assembly->culture = p;
7177 while (*p && *p != ',') {
7178 p++;
7181 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7182 p += 15;
7183 if (strncmp (p, "null", 4) == 0) {
7184 p += 4;
7185 } else {
7186 int len;
7187 gchar *start = p;
7188 while (*p && *p != ',') {
7189 p++;
7191 len = (p - start + 1);
7192 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7193 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7194 g_strlcpy ((char*)assembly->public_key_token, start, len);
7196 } else {
7197 while (*p && *p != ',')
7198 p++;
7200 found_sep = 0;
7201 while (g_ascii_isspace (*p) || *p == ',') {
7202 *p++ = 0;
7203 found_sep = 1;
7204 continue;
7206 /* failed */
7207 if (!found_sep)
7208 return 1;
7211 return 0;
7215 * mono_reflection_parse_type:
7216 * @name: type name
7218 * Parse a type name as accepted by the GetType () method and output the info
7219 * extracted in the info structure.
7220 * the name param will be mangled, so, make a copy before passing it to this function.
7221 * The fields in info will be valid until the memory pointed to by name is valid.
7223 * See also mono_type_get_name () below.
7225 * Returns: 0 on parse error.
7227 static int
7228 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7229 MonoTypeNameParse *info)
7231 char *start, *p, *w, *temp, *last_point, *startn;
7232 int in_modifiers = 0;
7233 int isbyref = 0, rank, arity = 0, i;
7235 start = p = w = name;
7237 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7238 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7239 info->name = info->name_space = NULL;
7240 info->nested = NULL;
7241 info->modifiers = NULL;
7242 info->type_arguments = NULL;
7244 /* last_point separates the namespace from the name */
7245 last_point = NULL;
7246 /* Skips spaces */
7247 while (*p == ' ') p++, start++, w++, name++;
7249 while (*p) {
7250 switch (*p) {
7251 case '+':
7252 *p = 0; /* NULL terminate the name */
7253 startn = p + 1;
7254 info->nested = g_list_append (info->nested, startn);
7255 /* we have parsed the nesting namespace + name */
7256 if (info->name)
7257 break;
7258 if (last_point) {
7259 info->name_space = start;
7260 *last_point = 0;
7261 info->name = last_point + 1;
7262 } else {
7263 info->name_space = (char *)"";
7264 info->name = start;
7266 break;
7267 case '.':
7268 last_point = p;
7269 break;
7270 case '\\':
7271 ++p;
7272 break;
7273 case '&':
7274 case '*':
7275 case '[':
7276 case ',':
7277 case ']':
7278 in_modifiers = 1;
7279 break;
7280 case '`':
7281 ++p;
7282 i = strtol (p, &temp, 10);
7283 arity += i;
7284 if (p == temp)
7285 return 0;
7286 p = temp-1;
7287 break;
7288 default:
7289 break;
7291 if (in_modifiers)
7292 break;
7293 // *w++ = *p++;
7294 p++;
7297 if (!info->name) {
7298 if (last_point) {
7299 info->name_space = start;
7300 *last_point = 0;
7301 info->name = last_point + 1;
7302 } else {
7303 info->name_space = (char *)"";
7304 info->name = start;
7307 while (*p) {
7308 switch (*p) {
7309 case '&':
7310 if (isbyref) /* only one level allowed by the spec */
7311 return 0;
7312 isbyref = 1;
7313 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7314 *p++ = 0;
7315 break;
7316 case '*':
7317 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7318 *p++ = 0;
7319 break;
7320 case '[':
7321 if (arity != 0) {
7322 *p++ = 0;
7323 info->type_arguments = g_ptr_array_new ();
7324 for (i = 0; i < arity; i++) {
7325 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7326 gboolean fqname = FALSE;
7328 g_ptr_array_add (info->type_arguments, subinfo);
7330 if (*p == '[') {
7331 p++;
7332 fqname = TRUE;
7335 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7336 return 0;
7338 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7339 if (fqname && (*p != ']')) {
7340 char *aname;
7342 if (*p != ',')
7343 return 0;
7344 *p++ = 0;
7346 aname = p;
7347 while (*p && (*p != ']'))
7348 p++;
7350 if (*p != ']')
7351 return 0;
7353 *p++ = 0;
7354 while (*aname) {
7355 if (g_ascii_isspace (*aname)) {
7356 ++aname;
7357 continue;
7359 break;
7361 if (!*aname ||
7362 !assembly_name_to_aname (&subinfo->assembly, aname))
7363 return 0;
7364 } else if (fqname && (*p == ']')) {
7365 *p++ = 0;
7368 if (i + 1 < arity) {
7369 if (*p != ',')
7370 return 0;
7371 } else {
7372 if (*p != ']')
7373 return 0;
7375 *p++ = 0;
7378 arity = 0;
7379 break;
7381 rank = 1;
7382 *p++ = 0;
7383 while (*p) {
7384 if (*p == ']')
7385 break;
7386 if (*p == ',')
7387 rank++;
7388 else if (*p == '*') /* '*' means unknown lower bound */
7389 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7390 else
7391 return 0;
7392 ++p;
7394 if (*p++ != ']')
7395 return 0;
7396 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7397 break;
7398 case ']':
7399 if (is_recursed)
7400 goto end;
7401 return 0;
7402 case ',':
7403 if (is_recursed)
7404 goto end;
7405 *p++ = 0;
7406 while (*p) {
7407 if (g_ascii_isspace (*p)) {
7408 ++p;
7409 continue;
7411 break;
7413 if (!*p)
7414 return 0; /* missing assembly name */
7415 if (!assembly_name_to_aname (&info->assembly, p))
7416 return 0;
7417 break;
7418 default:
7419 return 0;
7421 if (info->assembly.name)
7422 break;
7424 // *w = 0; /* terminate class name */
7425 end:
7426 if (!info->name || !*info->name)
7427 return 0;
7428 if (endptr)
7429 *endptr = p;
7430 /* add other consistency checks */
7431 return 1;
7435 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7437 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7440 static MonoType*
7441 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7443 gboolean type_resolve = FALSE;
7444 MonoType *type;
7445 MonoImage *rootimage = image;
7447 if (info->assembly.name) {
7448 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7449 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7451 * This could happen in the AOT compiler case when the search hook is not
7452 * installed.
7454 assembly = image->assembly;
7455 if (!assembly) {
7456 /* then we must load the assembly ourselve - see #60439 */
7457 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7458 if (!assembly)
7459 return NULL;
7461 image = assembly->image;
7462 } else if (!image) {
7463 image = mono_defaults.corlib;
7466 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7467 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7468 image = mono_defaults.corlib;
7469 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7472 return type;
7475 static MonoType*
7476 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7478 MonoClass *klass;
7479 GList *mod;
7480 int modval;
7481 gboolean bounded = FALSE;
7483 if (!image)
7484 image = mono_defaults.corlib;
7486 if (ignorecase)
7487 klass = mono_class_from_name_case (image, info->name_space, info->name);
7488 else
7489 klass = mono_class_from_name (image, info->name_space, info->name);
7490 if (!klass)
7491 return NULL;
7492 for (mod = info->nested; mod; mod = mod->next) {
7493 gpointer iter = NULL;
7494 MonoClass *parent;
7496 parent = klass;
7497 mono_class_init (parent);
7499 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7500 if (ignorecase) {
7501 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7502 break;
7503 } else {
7504 if (strcmp (klass->name, mod->data) == 0)
7505 break;
7508 if (!klass)
7509 break;
7511 if (!klass)
7512 return NULL;
7513 mono_class_init (klass);
7515 if (info->type_arguments) {
7516 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7517 MonoReflectionType *the_type;
7518 MonoType *instance;
7519 int i;
7521 for (i = 0; i < info->type_arguments->len; i++) {
7522 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7524 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7525 if (!type_args [i]) {
7526 g_free (type_args);
7527 return NULL;
7531 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7533 instance = mono_reflection_bind_generic_parameters (
7534 the_type, info->type_arguments->len, type_args);
7536 g_free (type_args);
7537 if (!instance)
7538 return NULL;
7540 klass = mono_class_from_mono_type (instance);
7543 for (mod = info->modifiers; mod; mod = mod->next) {
7544 modval = GPOINTER_TO_UINT (mod->data);
7545 if (!modval) { /* byref: must be last modifier */
7546 return &klass->this_arg;
7547 } else if (modval == -1) {
7548 klass = mono_ptr_class_get (&klass->byval_arg);
7549 } else if (modval == -2) {
7550 bounded = TRUE;
7551 } else { /* array rank */
7552 klass = mono_bounded_array_class_get (klass, modval, bounded);
7554 mono_class_init (klass);
7557 return &klass->byval_arg;
7561 * mono_reflection_get_type:
7562 * @image: a metadata context
7563 * @info: type description structure
7564 * @ignorecase: flag for case-insensitive string compares
7565 * @type_resolve: whenever type resolve was already tried
7567 * Build a MonoType from the type description in @info.
7571 MonoType*
7572 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7573 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7576 static MonoType*
7577 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7579 MonoReflectionAssemblyBuilder *abuilder;
7580 MonoType *type;
7581 int i;
7583 g_assert (assembly->dynamic);
7584 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7586 /* Enumerate all modules */
7588 type = NULL;
7589 if (abuilder->modules) {
7590 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7591 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7592 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7593 if (type)
7594 break;
7598 if (!type && abuilder->loaded_modules) {
7599 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7600 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7601 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7602 if (type)
7603 break;
7607 return type;
7610 MonoType*
7611 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7613 MonoType *type;
7614 MonoReflectionAssembly *assembly;
7615 GString *fullName;
7616 GList *mod;
7618 if (image && image->dynamic)
7619 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7620 else
7621 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7622 if (type)
7623 return type;
7624 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7625 return NULL;
7627 if (type_resolve) {
7628 if (*type_resolve)
7629 return NULL;
7630 else
7631 *type_resolve = TRUE;
7634 /* Reconstruct the type name */
7635 fullName = g_string_new ("");
7636 if (info->name_space && (info->name_space [0] != '\0'))
7637 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7638 else
7639 g_string_printf (fullName, "%s", info->name);
7640 for (mod = info->nested; mod; mod = mod->next)
7641 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7643 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7644 if (assembly) {
7645 if (assembly->assembly->dynamic)
7646 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7647 else
7648 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7649 info, ignorecase);
7651 g_string_free (fullName, TRUE);
7652 return type;
7655 void
7656 mono_reflection_free_type_info (MonoTypeNameParse *info)
7658 g_list_free (info->modifiers);
7659 g_list_free (info->nested);
7661 if (info->type_arguments) {
7662 int i;
7664 for (i = 0; i < info->type_arguments->len; i++) {
7665 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7667 mono_reflection_free_type_info (subinfo);
7668 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7669 g_free (subinfo);
7672 g_ptr_array_free (info->type_arguments, TRUE);
7677 * mono_reflection_type_from_name:
7678 * @name: type name.
7679 * @image: a metadata context (can be NULL).
7681 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7682 * it defaults to get the type from @image or, if @image is NULL or loading
7683 * from it fails, uses corlib.
7686 MonoType*
7687 mono_reflection_type_from_name (char *name, MonoImage *image)
7689 MonoType *type = NULL;
7690 MonoTypeNameParse info;
7691 char *tmp;
7693 /* Make a copy since parse_type modifies its argument */
7694 tmp = g_strdup (name);
7696 /*g_print ("requested type %s\n", str);*/
7697 if (mono_reflection_parse_type (tmp, &info)) {
7698 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7701 g_free (tmp);
7702 mono_reflection_free_type_info (&info);
7703 return type;
7707 * mono_reflection_get_token:
7709 * Return the metadata token of OBJ which should be an object
7710 * representing a metadata element.
7712 guint32
7713 mono_reflection_get_token (MonoObject *obj)
7715 MonoClass *klass;
7716 guint32 token = 0;
7718 klass = obj->vtable->klass;
7720 if (strcmp (klass->name, "MethodBuilder") == 0) {
7721 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7723 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7724 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7725 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7727 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7728 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7729 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7731 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7732 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7733 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7734 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7735 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7736 } else if (strcmp (klass->name, "MonoType") == 0) {
7737 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7738 MonoClass *mc = mono_class_from_mono_type (type);
7739 if (!mono_class_init (mc))
7740 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7742 token = mc->type_token;
7743 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7744 strcmp (klass->name, "MonoMethod") == 0 ||
7745 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7746 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7747 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7748 if (m->method->is_inflated) {
7749 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7750 return inflated->declaring->token;
7751 } else {
7752 token = m->method->token;
7754 } else if (strcmp (klass->name, "MonoField") == 0) {
7755 MonoReflectionField *f = (MonoReflectionField*)obj;
7757 if (is_field_on_inst (f->field)) {
7758 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7759 int field_index = f->field - dgclass->fields;
7760 MonoObject *obj;
7762 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7763 obj = dgclass->field_objects [field_index];
7764 return mono_reflection_get_token (obj);
7766 token = mono_class_get_field_token (f->field);
7767 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7768 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7770 token = mono_class_get_property_token (p->property);
7771 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7772 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7774 token = mono_class_get_event_token (p->event);
7775 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7776 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7777 MonoClass *member_class = mono_object_class (p->MemberImpl);
7778 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7780 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7781 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7782 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7784 token = m->token;
7785 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7786 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7787 } else {
7788 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7789 MonoException *ex = mono_get_exception_not_implemented (msg);
7790 g_free (msg);
7791 mono_raise_exception (ex);
7794 return token;
7797 static void*
7798 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7800 int slen, type = t->type;
7801 MonoClass *tklass = t->data.klass;
7803 handle_enum:
7804 switch (type) {
7805 case MONO_TYPE_U1:
7806 case MONO_TYPE_I1:
7807 case MONO_TYPE_BOOLEAN: {
7808 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7809 *bval = *p;
7810 *end = p + 1;
7811 return bval;
7813 case MONO_TYPE_CHAR:
7814 case MONO_TYPE_U2:
7815 case MONO_TYPE_I2: {
7816 guint16 *val = g_malloc (sizeof (guint16));
7817 *val = read16 (p);
7818 *end = p + 2;
7819 return val;
7821 #if SIZEOF_VOID_P == 4
7822 case MONO_TYPE_U:
7823 case MONO_TYPE_I:
7824 #endif
7825 case MONO_TYPE_R4:
7826 case MONO_TYPE_U4:
7827 case MONO_TYPE_I4: {
7828 guint32 *val = g_malloc (sizeof (guint32));
7829 *val = read32 (p);
7830 *end = p + 4;
7831 return val;
7833 #if SIZEOF_VOID_P == 8
7834 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7835 case MONO_TYPE_I:
7836 #endif
7837 case MONO_TYPE_U8:
7838 case MONO_TYPE_I8: {
7839 guint64 *val = g_malloc (sizeof (guint64));
7840 *val = read64 (p);
7841 *end = p + 8;
7842 return val;
7844 case MONO_TYPE_R8: {
7845 double *val = g_malloc (sizeof (double));
7846 readr8 (p, val);
7847 *end = p + 8;
7848 return val;
7850 case MONO_TYPE_VALUETYPE:
7851 if (t->data.klass->enumtype) {
7852 type = mono_class_enum_basetype (t->data.klass)->type;
7853 goto handle_enum;
7854 } else {
7855 MonoClass *k = t->data.klass;
7857 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7858 guint64 *val = g_malloc (sizeof (guint64));
7859 *val = read64 (p);
7860 *end = p + 8;
7861 return val;
7864 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7865 break;
7867 case MONO_TYPE_STRING:
7868 if (*p == (char)0xFF) {
7869 *end = p + 1;
7870 return NULL;
7872 slen = mono_metadata_decode_value (p, &p);
7873 *end = p + slen;
7874 return mono_string_new_len (mono_domain_get (), p, slen);
7875 case MONO_TYPE_CLASS: {
7876 char *n;
7877 MonoType *t;
7878 if (*p == (char)0xFF) {
7879 *end = p + 1;
7880 return NULL;
7882 handle_type:
7883 slen = mono_metadata_decode_value (p, &p);
7884 n = g_memdup (p, slen + 1);
7885 n [slen] = 0;
7886 t = mono_reflection_type_from_name (n, image);
7887 if (!t)
7888 g_warning ("Cannot load type '%s'", n);
7889 g_free (n);
7890 *end = p + slen;
7891 if (t)
7892 return mono_type_get_object (mono_domain_get (), t);
7893 else
7894 return NULL;
7896 case MONO_TYPE_OBJECT: {
7897 char subt = *p++;
7898 MonoObject *obj;
7899 MonoClass *subc = NULL;
7900 void *val;
7902 if (subt == 0x50) {
7903 goto handle_type;
7904 } else if (subt == 0x0E) {
7905 type = MONO_TYPE_STRING;
7906 goto handle_enum;
7907 } else if (subt == 0x1D) {
7908 MonoType simple_type = {{0}};
7909 int etype = *p;
7910 p ++;
7912 if (etype == 0x51)
7913 /* See Partition II, Appendix B3 */
7914 etype = MONO_TYPE_OBJECT;
7915 type = MONO_TYPE_SZARRAY;
7916 simple_type.type = etype;
7917 tklass = mono_class_from_mono_type (&simple_type);
7918 goto handle_enum;
7919 } else if (subt == 0x55) {
7920 char *n;
7921 MonoType *t;
7922 slen = mono_metadata_decode_value (p, &p);
7923 n = g_memdup (p, slen + 1);
7924 n [slen] = 0;
7925 t = mono_reflection_type_from_name (n, image);
7926 if (!t)
7927 g_error ("Cannot load type '%s'", n);
7928 g_free (n);
7929 p += slen;
7930 subc = mono_class_from_mono_type (t);
7931 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7932 MonoType simple_type = {{0}};
7933 simple_type.type = subt;
7934 subc = mono_class_from_mono_type (&simple_type);
7935 } else {
7936 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7938 val = load_cattr_value (image, &subc->byval_arg, p, end);
7939 obj = mono_object_new (mono_domain_get (), subc);
7940 g_assert (!subc->has_references);
7941 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7942 g_free (val);
7943 return obj;
7945 case MONO_TYPE_SZARRAY: {
7946 MonoArray *arr;
7947 guint32 i, alen, basetype;
7948 alen = read32 (p);
7949 p += 4;
7950 if (alen == 0xffffffff) {
7951 *end = p;
7952 return NULL;
7954 arr = mono_array_new (mono_domain_get(), tklass, alen);
7955 basetype = tklass->byval_arg.type;
7956 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7957 basetype = mono_class_enum_basetype (tklass)->type;
7958 switch (basetype)
7960 case MONO_TYPE_U1:
7961 case MONO_TYPE_I1:
7962 case MONO_TYPE_BOOLEAN:
7963 for (i = 0; i < alen; i++) {
7964 MonoBoolean val = *p++;
7965 mono_array_set (arr, MonoBoolean, i, val);
7967 break;
7968 case MONO_TYPE_CHAR:
7969 case MONO_TYPE_U2:
7970 case MONO_TYPE_I2:
7971 for (i = 0; i < alen; i++) {
7972 guint16 val = read16 (p);
7973 mono_array_set (arr, guint16, i, val);
7974 p += 2;
7976 break;
7977 case MONO_TYPE_R4:
7978 case MONO_TYPE_U4:
7979 case MONO_TYPE_I4:
7980 for (i = 0; i < alen; i++) {
7981 guint32 val = read32 (p);
7982 mono_array_set (arr, guint32, i, val);
7983 p += 4;
7985 break;
7986 case MONO_TYPE_R8:
7987 for (i = 0; i < alen; i++) {
7988 double val;
7989 readr8 (p, &val);
7990 mono_array_set (arr, double, i, val);
7991 p += 8;
7993 break;
7994 case MONO_TYPE_U8:
7995 case MONO_TYPE_I8:
7996 for (i = 0; i < alen; i++) {
7997 guint64 val = read64 (p);
7998 mono_array_set (arr, guint64, i, val);
7999 p += 8;
8001 break;
8002 case MONO_TYPE_CLASS:
8003 case MONO_TYPE_OBJECT:
8004 case MONO_TYPE_STRING:
8005 for (i = 0; i < alen; i++) {
8006 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
8007 mono_array_setref (arr, i, item);
8009 break;
8010 default:
8011 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8013 *end=p;
8014 return arr;
8016 default:
8017 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8019 return NULL;
8022 static MonoObject*
8023 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8025 static MonoClass *klass;
8026 static MonoMethod *ctor;
8027 MonoObject *retval;
8028 void *params [2], *unboxed;
8030 if (!klass)
8031 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8032 if (!ctor)
8033 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8035 params [0] = mono_type_get_object (mono_domain_get (), t);
8036 params [1] = val;
8037 retval = mono_object_new (mono_domain_get (), klass);
8038 unboxed = mono_object_unbox (retval);
8039 mono_runtime_invoke (ctor, unboxed, params, NULL);
8041 return retval;
8044 static MonoObject*
8045 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8047 static MonoClass *klass;
8048 static MonoMethod *ctor;
8049 MonoObject *retval;
8050 void *unboxed, *params [2];
8052 if (!klass)
8053 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8054 if (!ctor)
8055 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8057 params [0] = minfo;
8058 params [1] = typedarg;
8059 retval = mono_object_new (mono_domain_get (), klass);
8060 unboxed = mono_object_unbox (retval);
8061 mono_runtime_invoke (ctor, unboxed, params, NULL);
8063 return retval;
8066 static gboolean
8067 type_is_reference (MonoType *type)
8069 switch (type->type) {
8070 case MONO_TYPE_BOOLEAN:
8071 case MONO_TYPE_CHAR:
8072 case MONO_TYPE_U:
8073 case MONO_TYPE_I:
8074 case MONO_TYPE_U1:
8075 case MONO_TYPE_I1:
8076 case MONO_TYPE_U2:
8077 case MONO_TYPE_I2:
8078 case MONO_TYPE_U4:
8079 case MONO_TYPE_I4:
8080 case MONO_TYPE_U8:
8081 case MONO_TYPE_I8:
8082 case MONO_TYPE_R8:
8083 case MONO_TYPE_R4:
8084 case MONO_TYPE_VALUETYPE:
8085 return FALSE;
8086 default:
8087 return TRUE;
8091 static void
8092 free_param_data (MonoMethodSignature *sig, void **params) {
8093 int i;
8094 for (i = 0; i < sig->param_count; ++i) {
8095 if (!type_is_reference (sig->params [i]))
8096 g_free (params [i]);
8101 * Find the field index in the metadata FieldDef table.
8103 static guint32
8104 find_field_index (MonoClass *klass, MonoClassField *field) {
8105 int i;
8107 for (i = 0; i < klass->field.count; ++i) {
8108 if (field == &klass->fields [i])
8109 return klass->field.first + 1 + i;
8111 return 0;
8115 * Find the property index in the metadata Property table.
8117 static guint32
8118 find_property_index (MonoClass *klass, MonoProperty *property) {
8119 int i;
8121 for (i = 0; i < klass->ext->property.count; ++i) {
8122 if (property == &klass->ext->properties [i])
8123 return klass->ext->property.first + 1 + i;
8125 return 0;
8129 * Find the event index in the metadata Event table.
8131 static guint32
8132 find_event_index (MonoClass *klass, MonoEvent *event) {
8133 int i;
8135 for (i = 0; i < klass->ext->event.count; ++i) {
8136 if (event == &klass->ext->events [i])
8137 return klass->ext->event.first + 1 + i;
8139 return 0;
8142 static MonoObject*
8143 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8145 const char *p = (const char*)data;
8146 const char *named;
8147 guint32 i, j, num_named;
8148 MonoObject *attr;
8149 void *params_buf [32];
8150 void **params;
8151 MonoMethodSignature *sig;
8153 mono_class_init (method->klass);
8155 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8156 return NULL;
8158 if (len == 0) {
8159 attr = mono_object_new (mono_domain_get (), method->klass);
8160 mono_runtime_invoke (method, attr, NULL, NULL);
8161 return attr;
8164 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8165 return NULL;
8167 /*g_print ("got attr %s\n", method->klass->name);*/
8169 sig = mono_method_signature (method);
8170 if (sig->param_count < 32)
8171 params = params_buf;
8172 else
8173 /* Allocate using GC so it gets GC tracking */
8174 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8176 /* skip prolog */
8177 p += 2;
8178 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8179 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8182 named = p;
8183 attr = mono_object_new (mono_domain_get (), method->klass);
8184 mono_runtime_invoke (method, attr, params, NULL);
8185 free_param_data (method->signature, params);
8186 num_named = read16 (named);
8187 named += 2;
8188 for (j = 0; j < num_named; j++) {
8189 gint name_len;
8190 char *name, named_type, data_type;
8191 named_type = *named++;
8192 data_type = *named++; /* type of data */
8193 if (data_type == MONO_TYPE_SZARRAY)
8194 data_type = *named++;
8195 if (data_type == MONO_TYPE_ENUM) {
8196 gint type_len;
8197 char *type_name;
8198 type_len = mono_metadata_decode_blob_size (named, &named);
8199 type_name = g_malloc (type_len + 1);
8200 memcpy (type_name, named, type_len);
8201 type_name [type_len] = 0;
8202 named += type_len;
8203 /* FIXME: lookup the type and check type consistency */
8204 g_free (type_name);
8206 name_len = mono_metadata_decode_blob_size (named, &named);
8207 name = g_malloc (name_len + 1);
8208 memcpy (name, named, name_len);
8209 name [name_len] = 0;
8210 named += name_len;
8211 if (named_type == 0x53) {
8212 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8213 void *val = load_cattr_value (image, field->type, named, &named);
8214 mono_field_set_value (attr, field, val);
8215 if (!type_is_reference (field->type))
8216 g_free (val);
8217 } else if (named_type == 0x54) {
8218 MonoProperty *prop;
8219 void *pparams [1];
8220 MonoType *prop_type;
8222 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8223 /* can we have more that 1 arg in a custom attr named property? */
8224 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8225 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8226 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8227 mono_property_set_value (prop, attr, pparams, NULL);
8228 if (!type_is_reference (prop_type))
8229 g_free (pparams [0]);
8231 g_free (name);
8234 if (params != params_buf)
8235 mono_gc_free_fixed (params);
8237 return attr;
8241 * mono_reflection_create_custom_attr_data_args:
8243 * Create an array of typed and named arguments from the cattr blob given by DATA.
8244 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8245 * NAMED_ARG_INFO will contain information about the named arguments.
8247 void
8248 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)
8250 MonoArray *typedargs, *namedargs;
8251 MonoClass *attrklass;
8252 MonoDomain *domain;
8253 const char *p = (const char*)data;
8254 const char *named;
8255 guint32 i, j, num_named;
8256 CattrNamedArg *arginfo = NULL;
8258 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8259 return;
8261 mono_class_init (method->klass);
8263 *typed_args = NULL;
8264 *named_args = NULL;
8265 *named_arg_info = NULL;
8267 domain = mono_domain_get ();
8269 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8270 return;
8272 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8274 /* skip prolog */
8275 p += 2;
8276 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8277 MonoObject *obj;
8278 void *val;
8280 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8281 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8282 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8283 mono_array_setref (typedargs, i, obj);
8285 if (!type_is_reference (mono_method_signature (method)->params [i]))
8286 g_free (val);
8289 named = p;
8290 num_named = read16 (named);
8291 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8292 named += 2;
8293 attrklass = method->klass;
8295 arginfo = g_new0 (CattrNamedArg, num_named);
8296 *named_arg_info = arginfo;
8298 for (j = 0; j < num_named; j++) {
8299 gint name_len;
8300 char *name, named_type, data_type;
8301 named_type = *named++;
8302 data_type = *named++; /* type of data */
8303 if (data_type == MONO_TYPE_SZARRAY)
8304 data_type = *named++;
8305 if (data_type == MONO_TYPE_ENUM) {
8306 gint type_len;
8307 char *type_name;
8308 type_len = mono_metadata_decode_blob_size (named, &named);
8309 type_name = g_malloc (type_len + 1);
8310 memcpy (type_name, named, type_len);
8311 type_name [type_len] = 0;
8312 named += type_len;
8313 /* FIXME: lookup the type and check type consistency */
8314 g_free (type_name);
8316 name_len = mono_metadata_decode_blob_size (named, &named);
8317 name = g_malloc (name_len + 1);
8318 memcpy (name, named, name_len);
8319 name [name_len] = 0;
8320 named += name_len;
8321 if (named_type == 0x53) {
8322 MonoObject *obj;
8323 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8324 void *val;
8326 arginfo [j].type = field->type;
8327 arginfo [j].field = field;
8329 val = load_cattr_value (image, field->type, named, &named);
8330 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8331 mono_array_setref (namedargs, j, obj);
8332 if (!type_is_reference (field->type))
8333 g_free (val);
8334 } else if (named_type == 0x54) {
8335 MonoObject *obj;
8336 MonoType *prop_type;
8337 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8338 void *val;
8340 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8341 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8343 arginfo [j].type = prop_type;
8344 arginfo [j].prop = prop;
8346 val = load_cattr_value (image, prop_type, named, &named);
8347 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8348 mono_array_setref (namedargs, j, obj);
8349 if (!type_is_reference (prop_type))
8350 g_free (val);
8352 g_free (name);
8355 *typed_args = typedargs;
8356 *named_args = namedargs;
8359 static MonoObject*
8360 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8362 MonoArray *typedargs, *namedargs;
8363 static MonoMethod *ctor;
8364 MonoDomain *domain;
8365 MonoObject *attr;
8366 void *params [3];
8367 CattrNamedArg *arginfo;
8368 int i;
8370 mono_class_init (method->klass);
8372 if (!ctor)
8373 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
8375 domain = mono_domain_get ();
8376 if (len == 0) {
8377 /* This is for Attributes with no parameters */
8378 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8379 params [0] = mono_method_get_object (domain, method, NULL);
8380 params [1] = params [2] = NULL;
8381 mono_runtime_invoke (method, attr, params, NULL);
8382 return attr;
8385 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8386 if (!typedargs || !namedargs)
8387 return NULL;
8389 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8390 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8391 MonoObject *typedarg;
8393 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8394 mono_array_setref (typedargs, i, typedarg);
8397 for (i = 0; i < mono_array_length (namedargs); ++i) {
8398 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8399 MonoObject *typedarg, *namedarg, *minfo;
8401 if (arginfo [i].prop)
8402 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8403 else
8404 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8406 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8407 namedarg = create_cattr_named_arg (minfo, typedarg);
8409 mono_array_setref (namedargs, i, namedarg);
8412 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8413 params [0] = mono_method_get_object (domain, method, NULL);
8414 params [1] = typedargs;
8415 params [2] = namedargs;
8416 mono_runtime_invoke (ctor, attr, params, NULL);
8417 return attr;
8420 MonoArray*
8421 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8423 MonoArray *result;
8424 MonoObject *attr;
8425 int i;
8427 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8428 for (i = 0; i < cinfo->num_attrs; ++i) {
8429 if (!cinfo->attrs [i].ctor)
8430 /* The cattr type is not finished yet */
8431 /* We should include the type name but cinfo doesn't contain it */
8432 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8433 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8434 mono_array_setref (result, i, attr);
8436 return result;
8439 static MonoArray*
8440 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8442 MonoArray *result;
8443 MonoObject *attr;
8444 int i, n;
8446 n = 0;
8447 for (i = 0; i < cinfo->num_attrs; ++i) {
8448 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8449 n ++;
8452 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8453 n = 0;
8454 for (i = 0; i < cinfo->num_attrs; ++i) {
8455 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8456 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8457 mono_array_setref (result, n, attr);
8458 n ++;
8461 return result;
8464 static MonoArray*
8465 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8467 MonoArray *result;
8468 MonoObject *attr;
8469 int i;
8471 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8472 for (i = 0; i < cinfo->num_attrs; ++i) {
8473 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8474 mono_array_setref (result, i, attr);
8476 return result;
8480 * mono_custom_attrs_from_index:
8482 * Returns: NULL if no attributes are found or if a loading error occurs.
8484 MonoCustomAttrInfo*
8485 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8487 guint32 mtoken, i, len;
8488 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8489 MonoTableInfo *ca;
8490 MonoCustomAttrInfo *ainfo;
8491 GList *tmp, *list = NULL;
8492 const char *data;
8494 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8496 i = mono_metadata_custom_attrs_from_index (image, idx);
8497 if (!i)
8498 return NULL;
8499 i --;
8500 while (i < ca->rows) {
8501 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8502 break;
8503 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8504 ++i;
8506 len = g_list_length (list);
8507 if (!len)
8508 return NULL;
8509 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8510 ainfo->num_attrs = len;
8511 ainfo->image = image;
8512 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8513 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8514 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8515 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8516 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8517 mtoken |= MONO_TOKEN_METHOD_DEF;
8518 break;
8519 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8520 mtoken |= MONO_TOKEN_MEMBER_REF;
8521 break;
8522 default:
8523 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8524 break;
8526 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8527 if (!ainfo->attrs [i].ctor) {
8528 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8529 g_list_free (list);
8530 g_free (ainfo);
8531 return NULL;
8534 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8535 /*FIXME raising an exception here doesn't make any sense*/
8536 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8537 g_list_free (list);
8538 g_free (ainfo);
8539 return NULL;
8541 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8542 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8543 ainfo->attrs [i].data = (guchar*)data;
8545 g_list_free (list);
8547 return ainfo;
8550 MonoCustomAttrInfo*
8551 mono_custom_attrs_from_method (MonoMethod *method)
8553 guint32 idx;
8556 * An instantiated method has the same cattrs as the generic method definition.
8558 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8559 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8561 if (method->is_inflated)
8562 method = ((MonoMethodInflated *) method)->declaring;
8564 if (method->dynamic || method->klass->image->dynamic)
8565 return lookup_custom_attr (method->klass->image, method);
8567 if (!method->token)
8568 /* Synthetic methods */
8569 return NULL;
8571 idx = mono_method_get_index (method);
8572 idx <<= MONO_CUSTOM_ATTR_BITS;
8573 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8574 return mono_custom_attrs_from_index (method->klass->image, idx);
8577 MonoCustomAttrInfo*
8578 mono_custom_attrs_from_class (MonoClass *klass)
8580 guint32 idx;
8582 if (klass->generic_class)
8583 klass = klass->generic_class->container_class;
8585 if (klass->image->dynamic)
8586 return lookup_custom_attr (klass->image, klass);
8588 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8589 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8590 idx <<= MONO_CUSTOM_ATTR_BITS;
8591 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8592 } else {
8593 idx = mono_metadata_token_index (klass->type_token);
8594 idx <<= MONO_CUSTOM_ATTR_BITS;
8595 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8597 return mono_custom_attrs_from_index (klass->image, idx);
8600 MonoCustomAttrInfo*
8601 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8603 guint32 idx;
8605 if (assembly->image->dynamic)
8606 return lookup_custom_attr (assembly->image, assembly);
8607 idx = 1; /* there is only one assembly */
8608 idx <<= MONO_CUSTOM_ATTR_BITS;
8609 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8610 return mono_custom_attrs_from_index (assembly->image, idx);
8613 static MonoCustomAttrInfo*
8614 mono_custom_attrs_from_module (MonoImage *image)
8616 guint32 idx;
8618 if (image->dynamic)
8619 return lookup_custom_attr (image, image);
8620 idx = 1; /* there is only one module */
8621 idx <<= MONO_CUSTOM_ATTR_BITS;
8622 idx |= MONO_CUSTOM_ATTR_MODULE;
8623 return mono_custom_attrs_from_index (image, idx);
8626 MonoCustomAttrInfo*
8627 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8629 guint32 idx;
8631 if (klass->image->dynamic) {
8632 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8633 return lookup_custom_attr (klass->image, property);
8635 idx = find_property_index (klass, property);
8636 idx <<= MONO_CUSTOM_ATTR_BITS;
8637 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8638 return mono_custom_attrs_from_index (klass->image, idx);
8641 MonoCustomAttrInfo*
8642 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8644 guint32 idx;
8646 if (klass->image->dynamic) {
8647 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8648 return lookup_custom_attr (klass->image, event);
8650 idx = find_event_index (klass, event);
8651 idx <<= MONO_CUSTOM_ATTR_BITS;
8652 idx |= MONO_CUSTOM_ATTR_EVENT;
8653 return mono_custom_attrs_from_index (klass->image, idx);
8656 MonoCustomAttrInfo*
8657 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8659 guint32 idx;
8660 if (klass->image->dynamic) {
8661 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8662 return lookup_custom_attr (klass->image, field);
8664 idx = find_field_index (klass, field);
8665 idx <<= MONO_CUSTOM_ATTR_BITS;
8666 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8667 return mono_custom_attrs_from_index (klass->image, idx);
8670 MonoCustomAttrInfo*
8671 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8673 MonoTableInfo *ca;
8674 guint32 i, idx, method_index;
8675 guint32 param_list, param_last, param_pos, found;
8676 MonoImage *image;
8677 MonoReflectionMethodAux *aux;
8680 * An instantiated method has the same cattrs as the generic method definition.
8682 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8683 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8685 if (method->is_inflated)
8686 method = ((MonoMethodInflated *) method)->declaring;
8688 if (method->klass->image->dynamic) {
8689 MonoCustomAttrInfo *res, *ainfo;
8690 int size;
8692 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8693 if (!aux || !aux->param_cattr)
8694 return NULL;
8696 /* Need to copy since it will be freed later */
8697 ainfo = aux->param_cattr [param];
8698 if (!ainfo)
8699 return NULL;
8700 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8701 res = g_malloc0 (size);
8702 memcpy (res, ainfo, size);
8703 return res;
8706 image = method->klass->image;
8707 method_index = mono_method_get_index (method);
8708 if (!method_index)
8709 return NULL;
8710 ca = &image->tables [MONO_TABLE_METHOD];
8712 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8713 if (method_index == ca->rows) {
8714 ca = &image->tables [MONO_TABLE_PARAM];
8715 param_last = ca->rows + 1;
8716 } else {
8717 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8718 ca = &image->tables [MONO_TABLE_PARAM];
8720 found = FALSE;
8721 for (i = param_list; i < param_last; ++i) {
8722 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8723 if (param_pos == param) {
8724 found = TRUE;
8725 break;
8728 if (!found)
8729 return NULL;
8730 idx = i;
8731 idx <<= MONO_CUSTOM_ATTR_BITS;
8732 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8733 return mono_custom_attrs_from_index (image, idx);
8736 gboolean
8737 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8739 int i;
8740 MonoClass *klass;
8741 for (i = 0; i < ainfo->num_attrs; ++i) {
8742 klass = ainfo->attrs [i].ctor->klass;
8743 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8744 return TRUE;
8746 return FALSE;
8749 MonoObject*
8750 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8752 int i, attr_index;
8753 MonoClass *klass;
8754 MonoArray *attrs;
8756 attr_index = -1;
8757 for (i = 0; i < ainfo->num_attrs; ++i) {
8758 klass = ainfo->attrs [i].ctor->klass;
8759 if (mono_class_has_parent (klass, attr_klass)) {
8760 attr_index = i;
8761 break;
8764 if (attr_index == -1)
8765 return NULL;
8767 attrs = mono_custom_attrs_construct (ainfo);
8768 if (attrs)
8769 return mono_array_get (attrs, MonoObject*, attr_index);
8770 else
8771 return NULL;
8775 * mono_reflection_get_custom_attrs_info:
8776 * @obj: a reflection object handle
8778 * Return the custom attribute info for attributes defined for the
8779 * reflection handle @obj. The objects.
8781 * FIXME this function leaks like a sieve for SRE objects.
8783 MonoCustomAttrInfo*
8784 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8786 MonoClass *klass;
8787 MonoCustomAttrInfo *cinfo = NULL;
8789 klass = obj->vtable->klass;
8790 if (klass == mono_defaults.monotype_class) {
8791 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8792 klass = mono_class_from_mono_type (type);
8793 if (!mono_class_init (klass))
8794 mono_raise_exception (mono_class_get_exception_for_failure (klass));
8795 cinfo = mono_custom_attrs_from_class (klass);
8796 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8797 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8798 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8799 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8800 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8801 cinfo = mono_custom_attrs_from_module (module->image);
8802 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8803 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8804 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8805 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8806 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8807 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8808 } else if (strcmp ("MonoField", klass->name) == 0) {
8809 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8810 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8811 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8812 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8813 cinfo = mono_custom_attrs_from_method (rmethod->method);
8814 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8815 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8816 cinfo = mono_custom_attrs_from_method (rmethod->method);
8817 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8818 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8819 MonoClass *member_class = mono_object_class (param->MemberImpl);
8820 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8821 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8822 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8823 } else if (is_sr_mono_property (member_class)) {
8824 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8825 MonoMethod *method;
8826 if (!(method = prop->property->get))
8827 method = prop->property->set;
8828 g_assert (method);
8830 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8832 #ifndef DISABLE_REFLECTION_EMIT
8833 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8834 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8835 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8836 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8837 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8838 MonoMethod *method = NULL;
8839 if (is_sre_ctor_builder (mono_object_class (c->cb)))
8840 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8841 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8842 method = ((MonoReflectionMethod *)c->cb)->method;
8843 else
8844 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));
8846 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8848 #endif
8849 else {
8850 char *type_name = mono_type_get_full_name (member_class);
8851 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8852 MonoException *ex = mono_get_exception_not_supported (msg);
8853 g_free (type_name);
8854 g_free (msg);
8855 mono_raise_exception (ex);
8857 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8858 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8859 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8860 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8861 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8862 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8863 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8864 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8865 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8866 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8867 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8868 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8869 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8870 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8871 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8872 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8873 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8874 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8875 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8876 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8877 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8878 } else { /* handle other types here... */
8879 g_error ("get custom attrs not yet supported for %s", klass->name);
8882 return cinfo;
8886 * mono_reflection_get_custom_attrs_by_type:
8887 * @obj: a reflection object handle
8889 * Return an array with all the custom attributes defined of the
8890 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8891 * of that type are returned. The objects are fully build. Return NULL if a loading error
8892 * occurs.
8894 MonoArray*
8895 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8897 MonoArray *result;
8898 MonoCustomAttrInfo *cinfo;
8900 cinfo = mono_reflection_get_custom_attrs_info (obj);
8901 if (cinfo) {
8902 if (attr_klass)
8903 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8904 else
8905 result = mono_custom_attrs_construct (cinfo);
8906 if (!cinfo->cached)
8907 mono_custom_attrs_free (cinfo);
8908 } else {
8909 if (mono_loader_get_last_error ())
8910 return NULL;
8911 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8914 return result;
8918 * mono_reflection_get_custom_attrs:
8919 * @obj: a reflection object handle
8921 * Return an array with all the custom attributes defined of the
8922 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8923 * occurs.
8925 MonoArray*
8926 mono_reflection_get_custom_attrs (MonoObject *obj)
8928 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8932 * mono_reflection_get_custom_attrs_data:
8933 * @obj: a reflection obj handle
8935 * Returns an array of System.Reflection.CustomAttributeData,
8936 * which include information about attributes reflected on
8937 * types loaded using the Reflection Only methods
8939 MonoArray*
8940 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8942 MonoArray *result;
8943 MonoCustomAttrInfo *cinfo;
8945 cinfo = mono_reflection_get_custom_attrs_info (obj);
8946 if (cinfo) {
8947 result = mono_custom_attrs_data_construct (cinfo);
8948 if (!cinfo->cached)
8949 mono_custom_attrs_free (cinfo);
8950 } else
8951 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8953 return result;
8956 static MonoReflectionType*
8957 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8959 static MonoMethod *method_get_underlying_system_type = NULL;
8960 MonoMethod *usertype_method;
8962 if (!method_get_underlying_system_type)
8963 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8964 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8965 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8969 static gboolean
8970 is_corlib_type (MonoClass *class)
8972 return class->image == mono_defaults.corlib;
8975 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8976 static MonoClass *cached_class; \
8977 if (cached_class) \
8978 return cached_class == _class; \
8979 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8980 cached_class = _class; \
8981 return TRUE; \
8983 return FALSE; \
8984 } while (0) \
8987 #ifndef DISABLE_REFLECTION_EMIT
8988 static gboolean
8989 is_sre_array (MonoClass *class)
8991 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8994 static gboolean
8995 is_sre_byref (MonoClass *class)
8997 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9000 static gboolean
9001 is_sre_pointer (MonoClass *class)
9003 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9006 static gboolean
9007 is_sre_generic_instance (MonoClass *class)
9009 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9012 static gboolean
9013 is_sre_type_builder (MonoClass *class)
9015 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9018 static gboolean
9019 is_sre_method_builder (MonoClass *class)
9021 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9024 static gboolean
9025 is_sre_ctor_builder (MonoClass *class)
9027 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9030 static gboolean
9031 is_sre_field_builder (MonoClass *class)
9033 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9036 static gboolean
9037 is_sre_method_on_tb_inst (MonoClass *class)
9039 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9042 static gboolean
9043 is_sre_ctor_on_tb_inst (MonoClass *class)
9045 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9048 MonoType*
9049 mono_reflection_type_get_handle (MonoReflectionType* ref)
9051 MonoClass *class;
9052 if (!ref)
9053 return NULL;
9054 if (ref->type)
9055 return ref->type;
9057 if (is_usertype (ref)) {
9058 ref = mono_reflection_type_get_underlying_system_type (ref);
9059 if (ref == NULL || is_usertype (ref))
9060 return NULL;
9061 if (ref->type)
9062 return ref->type;
9065 class = mono_object_class (ref);
9067 if (is_sre_array (class)) {
9068 MonoType *res;
9069 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9070 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9071 g_assert (base);
9072 if (sre_array->rank == 0) //single dimentional array
9073 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9074 else
9075 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9076 sre_array->type.type = res;
9077 return res;
9078 } else if (is_sre_byref (class)) {
9079 MonoType *res;
9080 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9081 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9082 g_assert (base);
9083 res = &mono_class_from_mono_type (base)->this_arg;
9084 sre_byref->type.type = res;
9085 return res;
9086 } else if (is_sre_pointer (class)) {
9087 MonoType *res;
9088 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9089 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9090 g_assert (base);
9091 res = &mono_ptr_class_get (base)->byval_arg;
9092 sre_pointer->type.type = res;
9093 return res;
9094 } else if (is_sre_generic_instance (class)) {
9095 MonoType *res, **types;
9096 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9097 int i, count;
9099 count = mono_array_length (gclass->type_arguments);
9100 types = g_new0 (MonoType*, count);
9101 for (i = 0; i < count; ++i) {
9102 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9103 types [i] = mono_reflection_type_get_handle (t);
9104 if (!types[i]) {
9105 g_free (types);
9106 return NULL;
9110 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9111 g_free (types);
9112 g_assert (res);
9113 gclass->type.type = res;
9114 return res;
9117 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9118 return NULL;
9123 void
9124 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9126 mono_reflection_type_get_handle (type);
9129 void
9130 mono_reflection_register_with_runtime (MonoReflectionType *type)
9132 MonoType *res = mono_reflection_type_get_handle (type);
9133 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9134 MonoClass *class;
9136 if (!res)
9137 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9139 class = mono_class_from_mono_type (res);
9141 mono_loader_lock (); /*same locking as mono_type_get_object*/
9142 mono_domain_lock (domain);
9144 if (!class->image->dynamic) {
9145 mono_class_setup_supertypes (class);
9146 } else {
9147 if (!domain->type_hash)
9148 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
9149 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
9150 mono_g_hash_table_insert (domain->type_hash, res, type);
9152 mono_domain_unlock (domain);
9153 mono_loader_unlock ();
9157 * LOCKING: Assumes the loader lock is held.
9159 static MonoMethodSignature*
9160 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9161 MonoMethodSignature *sig;
9162 int count, i;
9164 count = parameters? mono_array_length (parameters): 0;
9166 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9167 sig->param_count = count;
9168 sig->sentinelpos = -1; /* FIXME */
9169 for (i = 0; i < count; ++i)
9170 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9171 return sig;
9175 * LOCKING: Assumes the loader lock is held.
9177 static MonoMethodSignature*
9178 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9179 MonoMethodSignature *sig;
9181 sig = parameters_to_signature (image, ctor->parameters);
9182 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9183 sig->ret = &mono_defaults.void_class->byval_arg;
9184 return sig;
9188 * LOCKING: Assumes the loader lock is held.
9190 static MonoMethodSignature*
9191 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9192 MonoMethodSignature *sig;
9194 sig = parameters_to_signature (image, method->parameters);
9195 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9196 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9197 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9198 return sig;
9201 static MonoMethodSignature*
9202 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9203 MonoMethodSignature *sig;
9205 sig = parameters_to_signature (NULL, method->parameters);
9206 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9207 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9208 sig->generic_param_count = 0;
9209 return sig;
9212 static void
9213 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9215 MonoClass *klass = mono_object_class (prop);
9216 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9217 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9218 *name = mono_string_to_utf8 (pb->name);
9219 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9220 } else {
9221 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9222 *name = g_strdup (p->property->name);
9223 if (p->property->get)
9224 *type = mono_method_signature (p->property->get)->ret;
9225 else
9226 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9230 static void
9231 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9233 MonoClass *klass = mono_object_class (field);
9234 if (strcmp (klass->name, "FieldBuilder") == 0) {
9235 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9236 *name = mono_string_to_utf8 (fb->name);
9237 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9238 } else {
9239 MonoReflectionField *f = (MonoReflectionField *)field;
9240 *name = g_strdup (mono_field_get_name (f->field));
9241 *type = f->field->type;
9245 #else /* DISABLE_REFLECTION_EMIT */
9247 void
9248 mono_reflection_register_with_runtime (MonoReflectionType *type)
9250 /* This is empty */
9253 static gboolean
9254 is_sre_type_builder (MonoClass *class)
9256 return FALSE;
9259 static gboolean
9260 is_sre_generic_instance (MonoClass *class)
9262 return FALSE;
9265 #endif /* !DISABLE_REFLECTION_EMIT */
9268 static gboolean
9269 is_sr_mono_field (MonoClass *class)
9271 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9274 static gboolean
9275 is_sr_mono_property (MonoClass *class)
9277 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9280 static gboolean
9281 is_sr_mono_method (MonoClass *class)
9283 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9286 static gboolean
9287 is_sr_mono_cmethod (MonoClass *class)
9289 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9292 static gboolean
9293 is_sr_mono_generic_method (MonoClass *class)
9295 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9298 static gboolean
9299 is_sr_mono_generic_cmethod (MonoClass *class)
9301 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9304 gboolean
9305 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9307 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9310 static gboolean
9311 is_usertype (MonoReflectionType *ref)
9313 MonoClass *class = mono_object_class (ref);
9314 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9317 static MonoReflectionType*
9318 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9320 if (!type || type->type)
9321 return type;
9323 if (is_usertype (type)) {
9324 type = mono_reflection_type_get_underlying_system_type (type);
9325 if (is_usertype (type))
9326 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9329 return type;
9332 * Encode a value in a custom attribute stream of bytes.
9333 * The value to encode is either supplied as an object in argument val
9334 * (valuetypes are boxed), or as a pointer to the data in the
9335 * argument argval.
9336 * @type represents the type of the value
9337 * @buffer is the start of the buffer
9338 * @p the current position in the buffer
9339 * @buflen contains the size of the buffer and is used to return the new buffer size
9340 * if this needs to be realloced.
9341 * @retbuffer and @retp return the start and the position of the buffer
9343 static void
9344 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9346 MonoTypeEnum simple_type;
9348 if ((p-buffer) + 10 >= *buflen) {
9349 char *newbuf;
9350 *buflen *= 2;
9351 newbuf = g_realloc (buffer, *buflen);
9352 p = newbuf + (p-buffer);
9353 buffer = newbuf;
9355 if (!argval)
9356 argval = ((char*)arg + sizeof (MonoObject));
9357 simple_type = type->type;
9358 handle_enum:
9359 switch (simple_type) {
9360 case MONO_TYPE_BOOLEAN:
9361 case MONO_TYPE_U1:
9362 case MONO_TYPE_I1:
9363 *p++ = *argval;
9364 break;
9365 case MONO_TYPE_CHAR:
9366 case MONO_TYPE_U2:
9367 case MONO_TYPE_I2:
9368 swap_with_size (p, argval, 2, 1);
9369 p += 2;
9370 break;
9371 case MONO_TYPE_U4:
9372 case MONO_TYPE_I4:
9373 case MONO_TYPE_R4:
9374 swap_with_size (p, argval, 4, 1);
9375 p += 4;
9376 break;
9377 case MONO_TYPE_R8:
9378 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9379 p [0] = argval [4];
9380 p [1] = argval [5];
9381 p [2] = argval [6];
9382 p [3] = argval [7];
9383 p [4] = argval [0];
9384 p [5] = argval [1];
9385 p [6] = argval [2];
9386 p [7] = argval [3];
9387 #else
9388 swap_with_size (p, argval, 8, 1);
9389 #endif
9390 p += 8;
9391 break;
9392 case MONO_TYPE_U8:
9393 case MONO_TYPE_I8:
9394 swap_with_size (p, argval, 8, 1);
9395 p += 8;
9396 break;
9397 case MONO_TYPE_VALUETYPE:
9398 if (type->data.klass->enumtype) {
9399 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9400 goto handle_enum;
9401 } else {
9402 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9404 break;
9405 case MONO_TYPE_STRING: {
9406 char *str;
9407 guint32 slen;
9408 if (!arg) {
9409 *p++ = 0xFF;
9410 break;
9412 str = mono_string_to_utf8 ((MonoString*)arg);
9413 slen = strlen (str);
9414 if ((p-buffer) + 10 + slen >= *buflen) {
9415 char *newbuf;
9416 *buflen *= 2;
9417 *buflen += slen;
9418 newbuf = g_realloc (buffer, *buflen);
9419 p = newbuf + (p-buffer);
9420 buffer = newbuf;
9422 mono_metadata_encode_value (slen, p, &p);
9423 memcpy (p, str, slen);
9424 p += slen;
9425 g_free (str);
9426 break;
9428 case MONO_TYPE_CLASS: {
9429 char *str;
9430 guint32 slen;
9431 if (!arg) {
9432 *p++ = 0xFF;
9433 break;
9435 handle_type:
9436 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9437 slen = strlen (str);
9438 if ((p-buffer) + 10 + slen >= *buflen) {
9439 char *newbuf;
9440 *buflen *= 2;
9441 *buflen += slen;
9442 newbuf = g_realloc (buffer, *buflen);
9443 p = newbuf + (p-buffer);
9444 buffer = newbuf;
9446 mono_metadata_encode_value (slen, p, &p);
9447 memcpy (p, str, slen);
9448 p += slen;
9449 g_free (str);
9450 break;
9452 case MONO_TYPE_SZARRAY: {
9453 int len, i;
9454 MonoClass *eclass, *arg_eclass;
9456 if (!arg) {
9457 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9458 break;
9460 len = mono_array_length ((MonoArray*)arg);
9461 *p++ = len & 0xff;
9462 *p++ = (len >> 8) & 0xff;
9463 *p++ = (len >> 16) & 0xff;
9464 *p++ = (len >> 24) & 0xff;
9465 *retp = p;
9466 *retbuffer = buffer;
9467 eclass = type->data.klass;
9468 arg_eclass = mono_object_class (arg)->element_class;
9470 if (!eclass) {
9471 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9472 eclass = mono_defaults.object_class;
9474 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9475 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9476 int elsize = mono_class_array_element_size (arg_eclass);
9477 for (i = 0; i < len; ++i) {
9478 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9479 elptr += elsize;
9481 } else if (eclass->valuetype && arg_eclass->valuetype) {
9482 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9483 int elsize = mono_class_array_element_size (eclass);
9484 for (i = 0; i < len; ++i) {
9485 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9486 elptr += elsize;
9488 } else {
9489 for (i = 0; i < len; ++i) {
9490 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9493 break;
9495 case MONO_TYPE_OBJECT: {
9496 MonoClass *klass;
9497 char *str;
9498 guint32 slen;
9501 * The parameter type is 'object' but the type of the actual
9502 * argument is not. So we have to add type information to the blob
9503 * too. This is completely undocumented in the spec.
9506 if (arg == NULL) {
9507 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9508 *p++ = 0xFF;
9509 break;
9512 klass = mono_object_class (arg);
9514 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9515 *p++ = 0x50;
9516 goto handle_type;
9517 } else if (klass->enumtype) {
9518 *p++ = 0x55;
9519 } else if (klass == mono_defaults.string_class) {
9520 simple_type = MONO_TYPE_STRING;
9521 *p++ = 0x0E;
9522 goto handle_enum;
9523 } else if (klass->rank == 1) {
9524 *p++ = 0x1D;
9525 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9526 /* See Partition II, Appendix B3 */
9527 *p++ = 0x51;
9528 else
9529 *p++ = klass->element_class->byval_arg.type;
9530 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9531 break;
9532 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9533 *p++ = simple_type = klass->byval_arg.type;
9534 goto handle_enum;
9535 } else {
9536 g_error ("unhandled type in custom attr");
9538 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9539 slen = strlen (str);
9540 if ((p-buffer) + 10 + slen >= *buflen) {
9541 char *newbuf;
9542 *buflen *= 2;
9543 *buflen += slen;
9544 newbuf = g_realloc (buffer, *buflen);
9545 p = newbuf + (p-buffer);
9546 buffer = newbuf;
9548 mono_metadata_encode_value (slen, p, &p);
9549 memcpy (p, str, slen);
9550 p += slen;
9551 g_free (str);
9552 simple_type = mono_class_enum_basetype (klass)->type;
9553 goto handle_enum;
9555 default:
9556 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9558 *retp = p;
9559 *retbuffer = buffer;
9562 static void
9563 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9565 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9566 char *str = type_get_qualified_name (type, NULL);
9567 int slen = strlen (str);
9569 *p++ = 0x55;
9571 * This seems to be optional...
9572 * *p++ = 0x80;
9574 mono_metadata_encode_value (slen, p, &p);
9575 memcpy (p, str, slen);
9576 p += slen;
9577 g_free (str);
9578 } else if (type->type == MONO_TYPE_OBJECT) {
9579 *p++ = 0x51;
9580 } else if (type->type == MONO_TYPE_CLASS) {
9581 /* it should be a type: encode_cattr_value () has the check */
9582 *p++ = 0x50;
9583 } else {
9584 mono_metadata_encode_value (type->type, p, &p);
9585 if (type->type == MONO_TYPE_SZARRAY)
9586 /* See the examples in Partition VI, Annex B */
9587 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9590 *retp = p;
9593 #ifndef DISABLE_REFLECTION_EMIT
9594 static void
9595 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9597 int len;
9598 /* Preallocate a large enough buffer */
9599 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9600 char *str = type_get_qualified_name (type, NULL);
9601 len = strlen (str);
9602 g_free (str);
9603 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9604 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9605 len = strlen (str);
9606 g_free (str);
9607 } else {
9608 len = 0;
9610 len += strlen (name);
9612 if ((p-buffer) + 20 + len >= *buflen) {
9613 char *newbuf;
9614 *buflen *= 2;
9615 *buflen += len;
9616 newbuf = g_realloc (buffer, *buflen);
9617 p = newbuf + (p-buffer);
9618 buffer = newbuf;
9621 encode_field_or_prop_type (type, p, &p);
9623 len = strlen (name);
9624 mono_metadata_encode_value (len, p, &p);
9625 memcpy (p, name, len);
9626 p += len;
9627 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9628 *retp = p;
9629 *retbuffer = buffer;
9633 * mono_reflection_get_custom_attrs_blob:
9634 * @ctor: custom attribute constructor
9635 * @ctorArgs: arguments o the constructor
9636 * @properties:
9637 * @propValues:
9638 * @fields:
9639 * @fieldValues:
9641 * Creates the blob of data that needs to be saved in the metadata and that represents
9642 * the custom attributed described by @ctor, @ctorArgs etc.
9643 * Returns: a Byte array representing the blob of data.
9645 MonoArray*
9646 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9648 MonoArray *result;
9649 MonoMethodSignature *sig;
9650 MonoObject *arg;
9651 char *buffer, *p;
9652 guint32 buflen, i;
9654 MONO_ARCH_SAVE_REGS;
9656 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9657 /* sig is freed later so allocate it in the heap */
9658 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9659 } else {
9660 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9663 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9664 buflen = 256;
9665 p = buffer = g_malloc (buflen);
9666 /* write the prolog */
9667 *p++ = 1;
9668 *p++ = 0;
9669 for (i = 0; i < sig->param_count; ++i) {
9670 arg = mono_array_get (ctorArgs, MonoObject*, i);
9671 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9673 i = 0;
9674 if (properties)
9675 i += mono_array_length (properties);
9676 if (fields)
9677 i += mono_array_length (fields);
9678 *p++ = i & 0xff;
9679 *p++ = (i >> 8) & 0xff;
9680 if (properties) {
9681 MonoObject *prop;
9682 for (i = 0; i < mono_array_length (properties); ++i) {
9683 MonoType *ptype;
9684 char *pname;
9686 prop = mono_array_get (properties, gpointer, i);
9687 get_prop_name_and_type (prop, &pname, &ptype);
9688 *p++ = 0x54; /* PROPERTY signature */
9689 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9690 g_free (pname);
9694 if (fields) {
9695 MonoObject *field;
9696 for (i = 0; i < mono_array_length (fields); ++i) {
9697 MonoType *ftype;
9698 char *fname;
9700 field = mono_array_get (fields, gpointer, i);
9701 get_field_name_and_type (field, &fname, &ftype);
9702 *p++ = 0x53; /* FIELD signature */
9703 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9704 g_free (fname);
9708 g_assert (p - buffer <= buflen);
9709 buflen = p - buffer;
9710 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9711 p = mono_array_addr (result, char, 0);
9712 memcpy (p, buffer, buflen);
9713 g_free (buffer);
9714 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9715 g_free (sig);
9716 return result;
9720 * mono_reflection_setup_internal_class:
9721 * @tb: a TypeBuilder object
9723 * Creates a MonoClass that represents the TypeBuilder.
9724 * This is a trick that lets us simplify a lot of reflection code
9725 * (and will allow us to support Build and Run assemblies easier).
9727 void
9728 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9730 MonoError error;
9731 MonoClass *klass, *parent;
9733 MONO_ARCH_SAVE_REGS;
9735 RESOLVE_TYPE (tb->parent);
9737 mono_loader_lock ();
9739 if (tb->parent) {
9740 /* check so we can compile corlib correctly */
9741 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9742 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9743 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9744 } else {
9745 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9747 } else {
9748 parent = NULL;
9751 /* the type has already being created: it means we just have to change the parent */
9752 if (tb->type.type) {
9753 klass = mono_class_from_mono_type (tb->type.type);
9754 klass->parent = NULL;
9755 /* fool mono_class_setup_parent */
9756 klass->supertypes = NULL;
9757 mono_class_setup_parent (klass, parent);
9758 mono_class_setup_mono_type (klass);
9759 mono_loader_unlock ();
9760 return;
9763 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9765 klass->image = &tb->module->dynamic_image->image;
9767 klass->inited = 1; /* we lie to the runtime */
9768 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9769 if (!mono_error_ok (&error))
9770 goto failure;
9771 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9772 if (!mono_error_ok (&error))
9773 goto failure;
9774 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9775 klass->flags = tb->attrs;
9777 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9779 klass->element_class = klass;
9781 if (mono_class_get_ref_info (klass) == NULL) {
9783 mono_class_set_ref_info (klass, tb);
9785 /* Put into cache so mono_class_get () will find it.
9786 Skip nested types as those should not be available on the global scope. */
9787 if (!tb->nesting_type) {
9788 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9789 } else {
9790 klass->image->reflection_info_unregister_classes =
9791 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9793 } else {
9794 g_assert (mono_class_get_ref_info (klass) == tb);
9797 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9798 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9800 if (parent != NULL) {
9801 mono_class_setup_parent (klass, parent);
9802 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9803 const char *old_n = klass->name;
9804 /* trick to get relative numbering right when compiling corlib */
9805 klass->name = "BuildingObject";
9806 mono_class_setup_parent (klass, mono_defaults.object_class);
9807 klass->name = old_n;
9810 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9811 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9812 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9813 klass->instance_size = sizeof (MonoObject);
9814 klass->size_inited = 1;
9815 mono_class_setup_vtable_general (klass, NULL, 0);
9818 mono_class_setup_mono_type (klass);
9820 mono_class_setup_supertypes (klass);
9823 * FIXME: handle interfaces.
9826 tb->type.type = &klass->byval_arg;
9828 if (tb->nesting_type) {
9829 g_assert (tb->nesting_type->type);
9830 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9833 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9835 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9837 mono_loader_unlock ();
9838 return;
9840 failure:
9841 mono_loader_unlock ();
9842 mono_error_raise_exception (&error);
9846 * mono_reflection_setup_generic_class:
9847 * @tb: a TypeBuilder object
9849 * Setup the generic class before adding the first generic parameter.
9851 void
9852 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9857 * mono_reflection_create_generic_class:
9858 * @tb: a TypeBuilder object
9860 * Creates the generic class after all generic parameters have been added.
9862 void
9863 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9865 MonoClass *klass;
9866 int count, i;
9868 MONO_ARCH_SAVE_REGS;
9870 klass = mono_class_from_mono_type (tb->type.type);
9872 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9874 if (klass->generic_container || (count == 0))
9875 return;
9877 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9879 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9881 klass->generic_container->owner.klass = klass;
9882 klass->generic_container->type_argc = count;
9883 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9885 klass->is_generic = 1;
9887 for (i = 0; i < count; i++) {
9888 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9889 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9890 klass->generic_container->type_params [i] = *param;
9891 /*Make sure we are a diferent type instance */
9892 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9893 klass->generic_container->type_params [i].info.pklass = NULL;
9894 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9896 g_assert (klass->generic_container->type_params [i].param.owner);
9899 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9903 * mono_reflection_create_internal_class:
9904 * @tb: a TypeBuilder object
9906 * Actually create the MonoClass that is associated with the TypeBuilder.
9908 void
9909 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9911 MonoClass *klass;
9913 MONO_ARCH_SAVE_REGS;
9915 klass = mono_class_from_mono_type (tb->type.type);
9917 mono_loader_lock ();
9918 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9919 MonoReflectionFieldBuilder *fb;
9920 MonoClass *ec;
9921 MonoType *enum_basetype;
9923 g_assert (tb->fields != NULL);
9924 g_assert (mono_array_length (tb->fields) >= 1);
9926 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9928 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9929 mono_loader_unlock ();
9930 return;
9933 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9934 klass->element_class = mono_class_from_mono_type (enum_basetype);
9935 if (!klass->element_class)
9936 klass->element_class = mono_class_from_mono_type (enum_basetype);
9939 * get the element_class from the current corlib.
9941 ec = default_class_from_mono_type (enum_basetype);
9942 klass->instance_size = ec->instance_size;
9943 klass->size_inited = 1;
9945 * this is almost safe to do with enums and it's needed to be able
9946 * to create objects of the enum type (for use in SetConstant).
9948 /* FIXME: Does this mean enums can't have method overrides ? */
9949 mono_class_setup_vtable_general (klass, NULL, 0);
9951 mono_loader_unlock ();
9954 static MonoMarshalSpec*
9955 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9956 MonoReflectionMarshal *minfo)
9958 MonoMarshalSpec *res;
9960 res = image_g_new0 (image, MonoMarshalSpec, 1);
9961 res->native = minfo->type;
9963 switch (minfo->type) {
9964 case MONO_NATIVE_LPARRAY:
9965 res->data.array_data.elem_type = minfo->eltype;
9966 if (minfo->has_size) {
9967 res->data.array_data.param_num = minfo->param_num;
9968 res->data.array_data.num_elem = minfo->count;
9969 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9971 else {
9972 res->data.array_data.param_num = -1;
9973 res->data.array_data.num_elem = -1;
9974 res->data.array_data.elem_mult = -1;
9976 break;
9978 case MONO_NATIVE_BYVALTSTR:
9979 case MONO_NATIVE_BYVALARRAY:
9980 res->data.array_data.num_elem = minfo->count;
9981 break;
9983 case MONO_NATIVE_CUSTOM:
9984 if (minfo->marshaltyperef)
9985 res->data.custom_data.custom_name =
9986 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9987 if (minfo->mcookie)
9988 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9989 break;
9991 default:
9992 break;
9995 return res;
9997 #endif /* !DISABLE_REFLECTION_EMIT */
9999 MonoReflectionMarshal*
10000 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10001 MonoMarshalSpec *spec)
10003 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
10004 MonoReflectionMarshal *minfo;
10005 MonoType *mtype;
10007 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
10008 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
10009 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
10010 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
10013 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
10014 minfo->type = spec->native;
10016 switch (minfo->type) {
10017 case MONO_NATIVE_LPARRAY:
10018 minfo->eltype = spec->data.array_data.elem_type;
10019 minfo->count = spec->data.array_data.num_elem;
10020 minfo->param_num = spec->data.array_data.param_num;
10021 break;
10023 case MONO_NATIVE_BYVALTSTR:
10024 case MONO_NATIVE_BYVALARRAY:
10025 minfo->count = spec->data.array_data.num_elem;
10026 break;
10028 case MONO_NATIVE_CUSTOM:
10029 if (spec->data.custom_data.custom_name) {
10030 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10031 if (mtype)
10032 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10034 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10036 if (spec->data.custom_data.cookie)
10037 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10038 break;
10040 default:
10041 break;
10044 return minfo;
10047 #ifndef DISABLE_REFLECTION_EMIT
10048 static MonoMethod*
10049 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10050 ReflectionMethodBuilder *rmb,
10051 MonoMethodSignature *sig)
10053 MonoError error;
10054 MonoMethod *m;
10055 MonoMethodWrapper *wrapperm;
10056 MonoMarshalSpec **specs;
10057 MonoReflectionMethodAux *method_aux;
10058 MonoImage *image;
10059 gboolean dynamic;
10060 int i;
10062 mono_error_init (&error);
10064 * Methods created using a MethodBuilder should have their memory allocated
10065 * inside the image mempool, while dynamic methods should have their memory
10066 * malloc'd.
10068 dynamic = rmb->refs != NULL;
10069 image = dynamic ? NULL : klass->image;
10071 if (!dynamic)
10072 g_assert (!klass->generic_class);
10074 mono_loader_lock ();
10076 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10077 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10078 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10079 else
10080 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10082 wrapperm = (MonoMethodWrapper*)m;
10084 m->dynamic = dynamic;
10085 m->slot = -1;
10086 m->flags = rmb->attrs;
10087 m->iflags = rmb->iattrs;
10088 m->name = mono_string_to_utf8_image (image, rmb->name, &error);
10089 g_assert (mono_error_ok (&error));
10090 m->klass = klass;
10091 m->signature = sig;
10092 m->sre_method = TRUE;
10093 m->skip_visibility = rmb->skip_visibility;
10094 if (rmb->table_idx)
10095 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10097 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10098 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10099 m->string_ctor = 1;
10101 m->signature->pinvoke = 1;
10102 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10103 m->signature->pinvoke = 1;
10105 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10107 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10108 g_assert (mono_error_ok (&error));
10109 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10110 g_assert (mono_error_ok (&error));
10112 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10114 if (klass->image->dynamic)
10115 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10117 mono_loader_unlock ();
10119 return m;
10120 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10121 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10122 MonoMethodHeader *header;
10123 guint32 code_size;
10124 gint32 max_stack, i;
10125 gint32 num_locals = 0;
10126 gint32 num_clauses = 0;
10127 guint8 *code;
10129 if (rmb->ilgen) {
10130 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10131 code_size = rmb->ilgen->code_len;
10132 max_stack = rmb->ilgen->max_stack;
10133 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10134 if (rmb->ilgen->ex_handlers)
10135 num_clauses = method_count_clauses (rmb->ilgen);
10136 } else {
10137 if (rmb->code) {
10138 code = mono_array_addr (rmb->code, guint8, 0);
10139 code_size = mono_array_length (rmb->code);
10140 /* we probably need to run a verifier on the code... */
10141 max_stack = 8;
10143 else {
10144 code = NULL;
10145 code_size = 0;
10146 max_stack = 8;
10150 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10151 header->code_size = code_size;
10152 header->code = image_g_malloc (image, code_size);
10153 memcpy ((char*)header->code, code, code_size);
10154 header->max_stack = max_stack;
10155 header->init_locals = rmb->init_locals;
10156 header->num_locals = num_locals;
10158 for (i = 0; i < num_locals; ++i) {
10159 MonoReflectionLocalBuilder *lb =
10160 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10162 header->locals [i] = image_g_new0 (image, MonoType, 1);
10163 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10166 header->num_clauses = num_clauses;
10167 if (num_clauses) {
10168 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10169 rmb->ilgen, num_clauses);
10172 wrapperm->header = header;
10175 if (rmb->generic_params) {
10176 int count = mono_array_length (rmb->generic_params);
10177 MonoGenericContainer *container = rmb->generic_container;
10179 g_assert (container);
10181 container->type_argc = count;
10182 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10183 container->owner.method = m;
10185 m->is_generic = TRUE;
10186 mono_method_set_generic_container (m, container);
10188 for (i = 0; i < count; i++) {
10189 MonoReflectionGenericParam *gp =
10190 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10191 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10192 container->type_params [i] = *param;
10196 * The method signature might have pointers to generic parameters that belong to other methods.
10197 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10198 * generic parameters.
10200 for (i = 0; i < m->signature->param_count; ++i) {
10201 MonoType *t = m->signature->params [i];
10202 if (t->type == MONO_TYPE_MVAR) {
10203 MonoGenericParam *gparam = t->data.generic_param;
10204 if (gparam->num < count) {
10205 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10206 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10212 if (klass->generic_container) {
10213 container->parent = klass->generic_container;
10214 container->context.class_inst = klass->generic_container->context.class_inst;
10216 container->context.method_inst = mono_get_shared_generic_inst (container);
10219 if (rmb->refs) {
10220 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10221 int i;
10222 void **data;
10224 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10226 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10227 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10228 for (i = 0; i < rmb->nrefs; ++i)
10229 data [i + 1] = rmb->refs [i];
10232 method_aux = NULL;
10234 /* Parameter info */
10235 if (rmb->pinfo) {
10236 if (!method_aux)
10237 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10238 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10239 for (i = 0; i <= m->signature->param_count; ++i) {
10240 MonoReflectionParamBuilder *pb;
10241 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10242 if ((i > 0) && (pb->attrs)) {
10243 /* Make a copy since it might point to a shared type structure */
10244 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10245 m->signature->params [i - 1]->attrs = pb->attrs;
10248 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10249 MonoDynamicImage *assembly;
10250 guint32 idx, def_type, len;
10251 char *p;
10252 const char *p2;
10254 if (!method_aux->param_defaults) {
10255 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10256 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10258 assembly = (MonoDynamicImage*)klass->image;
10259 idx = encode_constant (assembly, pb->def_value, &def_type);
10260 /* Copy the data from the blob since it might get realloc-ed */
10261 p = assembly->blob.data + idx;
10262 len = mono_metadata_decode_blob_size (p, &p2);
10263 len += p2 - p;
10264 method_aux->param_defaults [i] = image_g_malloc (image, len);
10265 method_aux->param_default_types [i] = def_type;
10266 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10269 if (pb->name) {
10270 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10271 g_assert (mono_error_ok (&error));
10273 if (pb->cattrs) {
10274 if (!method_aux->param_cattr)
10275 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10276 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10282 /* Parameter marshalling */
10283 specs = NULL;
10284 if (rmb->pinfo)
10285 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10286 MonoReflectionParamBuilder *pb;
10287 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10288 if (pb->marshal_info) {
10289 if (specs == NULL)
10290 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10291 specs [pb->position] =
10292 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10296 if (specs != NULL) {
10297 if (!method_aux)
10298 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10299 method_aux->param_marshall = specs;
10302 if (klass->image->dynamic && method_aux)
10303 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10305 mono_loader_unlock ();
10307 return m;
10310 static MonoMethod*
10311 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10313 ReflectionMethodBuilder rmb;
10314 MonoMethodSignature *sig;
10316 mono_loader_lock ();
10317 sig = ctor_builder_to_signature (klass->image, mb);
10318 mono_loader_unlock ();
10320 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10322 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10323 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10325 /* If we are in a generic class, we might be called multiple times from inflate_method */
10326 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10327 /* ilgen is no longer needed */
10328 mb->ilgen = NULL;
10331 return mb->mhandle;
10334 static MonoMethod*
10335 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10337 ReflectionMethodBuilder rmb;
10338 MonoMethodSignature *sig;
10340 mono_loader_lock ();
10341 sig = method_builder_to_signature (klass->image, mb);
10342 mono_loader_unlock ();
10344 reflection_methodbuilder_from_method_builder (&rmb, mb);
10346 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10347 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10349 /* If we are in a generic class, we might be called multiple times from inflate_method */
10350 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10351 /* ilgen is no longer needed */
10352 mb->ilgen = NULL;
10354 return mb->mhandle;
10357 static MonoClassField*
10358 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10360 MonoClassField *field;
10361 MonoType *custom;
10363 field = g_new0 (MonoClassField, 1);
10365 field->name = mono_string_to_utf8 (fb->name);
10366 if (fb->attrs || fb->modreq || fb->modopt) {
10367 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10368 field->type->attrs = fb->attrs;
10370 g_assert (klass->image->dynamic);
10371 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10372 g_free (field->type);
10373 field->type = custom;
10374 } else {
10375 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10377 if (fb->offset != -1)
10378 field->offset = fb->offset;
10379 field->parent = klass;
10380 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10382 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10384 return field;
10386 #endif
10388 MonoType*
10389 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10391 MonoClass *klass;
10392 MonoReflectionTypeBuilder *tb = NULL;
10393 gboolean is_dynamic = FALSE;
10394 MonoDomain *domain;
10395 MonoClass *geninst;
10397 mono_loader_lock ();
10399 domain = mono_object_domain (type);
10401 if (is_sre_type_builder (mono_object_class (type))) {
10402 tb = (MonoReflectionTypeBuilder *) type;
10404 is_dynamic = TRUE;
10405 } else if (is_sre_generic_instance (mono_object_class (type))) {
10406 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10407 MonoReflectionType *gtd = rgi->generic_type;
10409 if (is_sre_type_builder (mono_object_class (gtd))) {
10410 tb = (MonoReflectionTypeBuilder *)gtd;
10411 is_dynamic = TRUE;
10415 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10416 if (tb && tb->generic_container)
10417 mono_reflection_create_generic_class (tb);
10419 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10420 if (!klass->generic_container) {
10421 mono_loader_unlock ();
10422 return NULL;
10425 if (klass->wastypebuilder) {
10426 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10428 is_dynamic = TRUE;
10431 mono_loader_unlock ();
10433 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10435 return &geninst->byval_arg;
10438 MonoClass*
10439 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10441 MonoGenericClass *gclass;
10442 MonoGenericInst *inst;
10444 g_assert (klass->generic_container);
10446 inst = mono_metadata_get_generic_inst (type_argc, types);
10447 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10449 return mono_generic_class_get_class (gclass);
10452 MonoReflectionMethod*
10453 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10455 MonoClass *klass;
10456 MonoMethod *method, *inflated;
10457 MonoMethodInflated *imethod;
10458 MonoGenericContext tmp_context;
10459 MonoGenericInst *ginst;
10460 MonoType **type_argv;
10461 int count, i;
10463 MONO_ARCH_SAVE_REGS;
10465 /*FIXME but this no longer should happen*/
10466 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10467 #ifndef DISABLE_REFLECTION_EMIT
10468 MonoReflectionMethodBuilder *mb = NULL;
10469 MonoReflectionTypeBuilder *tb;
10470 MonoClass *klass;
10472 mb = (MonoReflectionMethodBuilder *) rmethod;
10473 tb = (MonoReflectionTypeBuilder *) mb->type;
10474 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10476 method = methodbuilder_to_mono_method (klass, mb);
10477 #else
10478 g_assert_not_reached ();
10479 method = NULL;
10480 #endif
10481 } else {
10482 method = rmethod->method;
10485 klass = method->klass;
10487 if (method->is_inflated)
10488 method = ((MonoMethodInflated *) method)->declaring;
10490 count = mono_method_signature (method)->generic_param_count;
10491 if (count != mono_array_length (types))
10492 return NULL;
10494 type_argv = g_new0 (MonoType *, count);
10495 for (i = 0; i < count; i++) {
10496 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10497 type_argv [i] = mono_reflection_type_get_handle (garg);
10499 ginst = mono_metadata_get_generic_inst (count, type_argv);
10500 g_free (type_argv);
10502 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10503 tmp_context.method_inst = ginst;
10505 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10506 imethod = (MonoMethodInflated *) inflated;
10508 /*FIXME but I think this is no longer necessary*/
10509 if (method->klass->image->dynamic) {
10510 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10512 * This table maps metadata structures representing inflated methods/fields
10513 * to the reflection objects representing their generic definitions.
10515 mono_loader_lock ();
10516 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10517 mono_loader_unlock ();
10520 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10523 #ifndef DISABLE_REFLECTION_EMIT
10525 static MonoMethod *
10526 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10528 MonoMethodInflated *imethod;
10529 MonoGenericContext *context;
10530 int i;
10533 * With generic code sharing the klass might not be inflated.
10534 * This can happen because classes inflated with their own
10535 * type arguments are "normalized" to the uninflated class.
10537 if (!klass->generic_class)
10538 return method;
10540 context = mono_class_get_context (klass);
10542 if (klass->method.count && klass->methods) {
10543 /* Find the already created inflated method */
10544 for (i = 0; i < klass->method.count; ++i) {
10545 g_assert (klass->methods [i]->is_inflated);
10546 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10547 break;
10549 g_assert (i < klass->method.count);
10550 imethod = (MonoMethodInflated*)klass->methods [i];
10551 } else {
10552 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10555 if (method->is_generic && method->klass->image->dynamic) {
10556 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10558 mono_loader_lock ();
10559 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10560 mono_loader_unlock ();
10562 return (MonoMethod *) imethod;
10565 static MonoMethod *
10566 inflate_method (MonoReflectionType *type, MonoObject *obj)
10568 MonoMethod *method;
10569 MonoClass *gklass;
10571 MonoClass *type_class = mono_object_class (type);
10573 if (is_sre_generic_instance (type_class)) {
10574 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10575 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10576 } else if (is_sre_type_builder (type_class)) {
10577 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10578 } else if (type->type) {
10579 gklass = mono_class_from_mono_type (type->type);
10580 gklass = mono_class_get_generic_type_definition (gklass);
10581 } else {
10582 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10585 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10586 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10587 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10588 else
10589 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10590 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10591 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10592 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10593 method = ((MonoReflectionMethod *) obj)->method;
10594 else {
10595 method = NULL; /* prevent compiler warning */
10596 g_error ("can't handle type %s", obj->vtable->klass->name);
10599 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10602 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10603 void
10604 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10605 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10606 MonoArray *events)
10608 MonoGenericClass *gclass;
10609 MonoDynamicGenericClass *dgclass;
10610 MonoClass *klass, *gklass;
10611 MonoType *gtype;
10612 int i;
10614 MONO_ARCH_SAVE_REGS;
10616 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10617 klass = mono_class_from_mono_type (gtype);
10618 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10619 gclass = gtype->data.generic_class;
10621 if (!gclass->is_dynamic)
10622 return;
10624 dgclass = (MonoDynamicGenericClass *) gclass;
10626 if (dgclass->initialized)
10627 return;
10629 gklass = gclass->container_class;
10630 mono_class_init (gklass);
10632 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10633 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10634 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10636 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10637 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10638 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10639 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10640 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10642 for (i = 0; i < dgclass->count_methods; i++) {
10643 MonoObject *obj = mono_array_get (methods, gpointer, i);
10645 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10648 for (i = 0; i < dgclass->count_ctors; i++) {
10649 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10651 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10654 for (i = 0; i < dgclass->count_fields; i++) {
10655 MonoObject *obj = mono_array_get (fields, gpointer, i);
10656 MonoClassField *field, *inflated_field = NULL;
10658 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10659 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10660 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10661 field = ((MonoReflectionField *) obj)->field;
10662 else {
10663 field = NULL; /* prevent compiler warning */
10664 g_assert_not_reached ();
10667 dgclass->fields [i] = *field;
10668 dgclass->fields [i].parent = klass;
10669 dgclass->fields [i].type = mono_class_inflate_generic_type (
10670 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10671 dgclass->field_generic_types [i] = field->type;
10672 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10673 dgclass->field_objects [i] = obj;
10675 if (inflated_field) {
10676 g_free (inflated_field);
10677 } else {
10678 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10682 dgclass->initialized = TRUE;
10685 static void
10686 fix_partial_generic_class (MonoClass *klass)
10688 MonoClass *gklass = klass->generic_class->container_class;
10689 MonoDynamicGenericClass *dgclass;
10690 int i;
10692 if (klass->wastypebuilder)
10693 return;
10695 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10696 if (klass->parent != gklass->parent) {
10697 MonoError error;
10698 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10699 if (mono_error_ok (&error)) {
10700 MonoClass *parent = mono_class_from_mono_type (parent_type);
10701 mono_metadata_free_type (parent_type);
10702 if (parent != klass->parent) {
10703 /*fool mono_class_setup_parent*/
10704 klass->supertypes = NULL;
10705 mono_class_setup_parent (klass, parent);
10707 } else {
10708 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10709 mono_error_cleanup (&error);
10710 if (gklass->wastypebuilder)
10711 klass->wastypebuilder = TRUE;
10712 return;
10716 if (!dgclass->initialized)
10717 return;
10719 if (klass->method.count != gklass->method.count) {
10720 klass->method.count = gklass->method.count;
10721 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10723 for (i = 0; i < klass->method.count; i++) {
10724 klass->methods [i] = mono_class_inflate_generic_method_full (
10725 gklass->methods [i], klass, mono_class_get_context (klass));
10729 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10730 klass->interface_count = gklass->interface_count;
10731 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10732 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10734 for (i = 0; i < gklass->interface_count; ++i) {
10735 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10736 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10737 mono_metadata_free_type (iface_type);
10739 ensure_runtime_vtable (klass->interfaces [i]);
10741 klass->interfaces_inited = 1;
10744 if (klass->field.count != gklass->field.count) {
10745 klass->field.count = gklass->field.count;
10746 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10748 for (i = 0; i < klass->field.count; i++) {
10749 klass->fields [i] = gklass->fields [i];
10750 klass->fields [i].parent = klass;
10751 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10755 /*We can only finish with this klass once it's parent has as well*/
10756 if (gklass->wastypebuilder)
10757 klass->wastypebuilder = TRUE;
10758 return;
10761 static void
10762 ensure_generic_class_runtime_vtable (MonoClass *klass)
10764 MonoClass *gklass = klass->generic_class->container_class;
10766 ensure_runtime_vtable (gklass);
10768 fix_partial_generic_class (klass);
10771 static void
10772 ensure_runtime_vtable (MonoClass *klass)
10774 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10775 int i, num, j;
10777 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10778 return;
10779 if (klass->parent)
10780 ensure_runtime_vtable (klass->parent);
10782 if (tb) {
10783 num = tb->ctors? mono_array_length (tb->ctors): 0;
10784 num += tb->num_methods;
10785 klass->method.count = num;
10786 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10787 num = tb->ctors? mono_array_length (tb->ctors): 0;
10788 for (i = 0; i < num; ++i)
10789 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10790 num = tb->num_methods;
10791 j = i;
10792 for (i = 0; i < num; ++i)
10793 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10795 if (tb->interfaces) {
10796 klass->interface_count = mono_array_length (tb->interfaces);
10797 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10798 for (i = 0; i < klass->interface_count; ++i) {
10799 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10800 klass->interfaces [i] = mono_class_from_mono_type (iface);
10801 ensure_runtime_vtable (klass->interfaces [i]);
10803 klass->interfaces_inited = 1;
10805 } else if (klass->generic_class){
10806 ensure_generic_class_runtime_vtable (klass);
10809 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10810 for (i = 0; i < klass->method.count; ++i)
10811 klass->methods [i]->slot = i;
10813 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10814 mono_class_setup_interface_offsets (klass);
10815 mono_class_setup_interface_id (klass);
10819 * The generic vtable is needed even if image->run is not set since some
10820 * runtime code like ves_icall_Type_GetMethodsByName depends on
10821 * method->slot being defined.
10825 * tb->methods could not be freed since it is used for determining
10826 * overrides during dynamic vtable construction.
10830 static MonoMethod*
10831 mono_reflection_method_get_handle (MonoObject *method)
10833 MonoClass *class = mono_object_class (method);
10834 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10835 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10836 return sr_method->method;
10838 if (is_sre_method_builder (class)) {
10839 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10840 return mb->mhandle;
10842 if (is_sre_method_on_tb_inst (class)) {
10843 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10844 MonoMethod *result;
10845 /*FIXME move this to a proper method and unify with resolve_object*/
10846 if (m->method_args) {
10847 result = mono_reflection_method_on_tb_inst_get_handle (m);
10848 } else {
10849 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10850 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10851 MonoMethod *mono_method;
10853 if (is_sre_method_builder (mono_object_class (m->mb)))
10854 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10855 else if (is_sr_mono_method (mono_object_class (m->mb)))
10856 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10857 else
10858 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)));
10860 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10862 return result;
10865 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10866 return NULL;
10869 void
10870 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10872 MonoReflectionTypeBuilder *tb;
10873 int i, onum;
10875 *overrides = NULL;
10876 *num_overrides = 0;
10878 g_assert (klass->image->dynamic);
10880 if (!mono_class_get_ref_info (klass))
10881 return;
10883 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10885 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10887 onum = 0;
10888 if (tb->methods) {
10889 for (i = 0; i < tb->num_methods; ++i) {
10890 MonoReflectionMethodBuilder *mb =
10891 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10892 if (mb->override_method)
10893 onum ++;
10897 if (onum) {
10898 *overrides = g_new0 (MonoMethod*, onum * 2);
10900 onum = 0;
10901 for (i = 0; i < tb->num_methods; ++i) {
10902 MonoReflectionMethodBuilder *mb =
10903 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10904 if (mb->override_method) {
10905 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10906 (*overrides) [onum * 2 + 1] = mb->mhandle;
10908 g_assert (mb->mhandle);
10910 onum ++;
10915 *num_overrides = onum;
10918 static void
10919 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10921 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10922 MonoReflectionFieldBuilder *fb;
10923 MonoClassField *field;
10924 MonoImage *image = klass->image;
10925 const char *p, *p2;
10926 int i;
10927 guint32 len, idx, real_size = 0;
10929 klass->field.count = tb->num_fields;
10930 klass->field.first = 0;
10932 mono_error_init (error);
10934 if (tb->class_size) {
10935 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10936 klass->packing_size = tb->packing_size;
10937 real_size = klass->instance_size + tb->class_size;
10940 if (!klass->field.count) {
10941 klass->instance_size = MAX (klass->instance_size, real_size);
10942 return;
10945 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10946 mono_class_alloc_ext (klass);
10947 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10949 This is, guess what, a hack.
10950 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10951 On the static path no field class is resolved, only types are built. This is the right thing to do
10952 but we suck.
10953 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10955 klass->size_inited = 1;
10957 for (i = 0; i < klass->field.count; ++i) {
10958 fb = mono_array_get (tb->fields, gpointer, i);
10959 field = &klass->fields [i];
10960 field->name = mono_string_to_utf8_image (image, fb->name, error);
10961 if (!mono_error_ok (error))
10962 return;
10963 if (fb->attrs) {
10964 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10965 field->type->attrs = fb->attrs;
10966 } else {
10967 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10969 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10970 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10971 if (fb->offset != -1)
10972 field->offset = fb->offset;
10973 field->parent = klass;
10974 fb->handle = field;
10975 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10977 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10978 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10980 if (fb->def_value) {
10981 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10982 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10983 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10984 /* Copy the data from the blob since it might get realloc-ed */
10985 p = assembly->blob.data + idx;
10986 len = mono_metadata_decode_blob_size (p, &p2);
10987 len += p2 - p;
10988 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10989 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10993 klass->instance_size = MAX (klass->instance_size, real_size);
10994 mono_class_layout_fields (klass);
10997 static void
10998 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11000 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11001 MonoReflectionPropertyBuilder *pb;
11002 MonoImage *image = klass->image;
11003 MonoProperty *properties;
11004 int i;
11006 mono_error_init (error);
11008 if (!klass->ext)
11009 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11011 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11012 klass->ext->property.first = 0;
11014 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11015 klass->ext->properties = properties;
11016 for (i = 0; i < klass->ext->property.count; ++i) {
11017 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11018 properties [i].parent = klass;
11019 properties [i].attrs = pb->attrs;
11020 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11021 if (!mono_error_ok (error))
11022 return;
11023 if (pb->get_method)
11024 properties [i].get = pb->get_method->mhandle;
11025 if (pb->set_method)
11026 properties [i].set = pb->set_method->mhandle;
11028 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11029 if (pb->def_value) {
11030 guint32 len, idx;
11031 const char *p, *p2;
11032 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11033 if (!klass->ext->prop_def_values)
11034 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11035 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11036 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11037 /* Copy the data from the blob since it might get realloc-ed */
11038 p = assembly->blob.data + idx;
11039 len = mono_metadata_decode_blob_size (p, &p2);
11040 len += p2 - p;
11041 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11042 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11047 MonoReflectionEvent *
11048 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11050 MonoEvent *event = g_new0 (MonoEvent, 1);
11051 MonoClass *klass;
11053 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11055 event->parent = klass;
11056 event->attrs = eb->attrs;
11057 event->name = mono_string_to_utf8 (eb->name);
11058 if (eb->add_method)
11059 event->add = eb->add_method->mhandle;
11060 if (eb->remove_method)
11061 event->remove = eb->remove_method->mhandle;
11062 if (eb->raise_method)
11063 event->raise = eb->raise_method->mhandle;
11065 #ifndef MONO_SMALL_CONFIG
11066 if (eb->other_methods) {
11067 int j;
11068 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11069 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11070 MonoReflectionMethodBuilder *mb =
11071 mono_array_get (eb->other_methods,
11072 MonoReflectionMethodBuilder*, j);
11073 event->other [j] = mb->mhandle;
11076 #endif
11078 return mono_event_get_object (mono_object_domain (tb), klass, event);
11081 static void
11082 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11084 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11085 MonoReflectionEventBuilder *eb;
11086 MonoImage *image = klass->image;
11087 MonoEvent *events;
11088 int i;
11090 mono_error_init (error);
11092 if (!klass->ext)
11093 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11095 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11096 klass->ext->event.first = 0;
11098 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11099 klass->ext->events = events;
11100 for (i = 0; i < klass->ext->event.count; ++i) {
11101 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11102 events [i].parent = klass;
11103 events [i].attrs = eb->attrs;
11104 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11105 if (!mono_error_ok (error))
11106 return;
11107 if (eb->add_method)
11108 events [i].add = eb->add_method->mhandle;
11109 if (eb->remove_method)
11110 events [i].remove = eb->remove_method->mhandle;
11111 if (eb->raise_method)
11112 events [i].raise = eb->raise_method->mhandle;
11114 #ifndef MONO_SMALL_CONFIG
11115 if (eb->other_methods) {
11116 int j;
11117 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11118 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11119 MonoReflectionMethodBuilder *mb =
11120 mono_array_get (eb->other_methods,
11121 MonoReflectionMethodBuilder*, j);
11122 events [i].other [j] = mb->mhandle;
11125 #endif
11126 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11130 static gboolean
11131 remove_instantiations_of_and_ensure_contents (gpointer key,
11132 gpointer value,
11133 gpointer user_data)
11135 MonoType *type = (MonoType*)key;
11136 MonoClass *klass = (MonoClass*)user_data;
11138 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11139 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11140 return TRUE;
11141 } else
11142 return FALSE;
11145 static void
11146 check_array_for_usertypes (MonoArray *arr)
11148 int i;
11150 if (!arr)
11151 return;
11153 for (i = 0; i < mono_array_length (arr); ++i)
11154 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11157 MonoReflectionType*
11158 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11160 MonoError error;
11161 MonoClass *klass;
11162 MonoDomain* domain;
11163 MonoReflectionType* res;
11164 int i, j;
11166 MONO_ARCH_SAVE_REGS;
11168 domain = mono_object_domain (tb);
11169 klass = mono_class_from_mono_type (tb->type.type);
11172 * Check for user defined Type subclasses.
11174 RESOLVE_TYPE (tb->parent);
11175 check_array_for_usertypes (tb->interfaces);
11176 if (tb->fields) {
11177 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11178 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11179 if (fb) {
11180 RESOLVE_TYPE (fb->type);
11181 check_array_for_usertypes (fb->modreq);
11182 check_array_for_usertypes (fb->modopt);
11183 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11184 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11188 if (tb->methods) {
11189 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11190 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11191 if (mb) {
11192 RESOLVE_TYPE (mb->rtype);
11193 check_array_for_usertypes (mb->return_modreq);
11194 check_array_for_usertypes (mb->return_modopt);
11195 check_array_for_usertypes (mb->parameters);
11196 if (mb->param_modreq)
11197 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11198 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11199 if (mb->param_modopt)
11200 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11201 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11205 if (tb->ctors) {
11206 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11207 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11208 if (mb) {
11209 check_array_for_usertypes (mb->parameters);
11210 if (mb->param_modreq)
11211 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11212 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11213 if (mb->param_modopt)
11214 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11215 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11220 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11223 * we need to lock the domain because the lock will be taken inside
11224 * So, we need to keep the locking order correct.
11226 mono_loader_lock ();
11227 mono_domain_lock (domain);
11228 if (klass->wastypebuilder) {
11229 mono_domain_unlock (domain);
11230 mono_loader_unlock ();
11231 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11234 * Fields to set in klass:
11235 * the various flags: delegate/unicode/contextbound etc.
11237 klass->flags = tb->attrs;
11238 klass->has_cctor = 1;
11239 klass->has_finalize = 1;
11241 /* fool mono_class_setup_parent */
11242 klass->supertypes = NULL;
11243 mono_class_setup_parent (klass, klass->parent);
11244 mono_class_setup_mono_type (klass);
11246 #if 0
11247 if (!((MonoDynamicImage*)klass->image)->run) {
11248 if (klass->generic_container) {
11249 /* FIXME: The code below can't handle generic classes */
11250 klass->wastypebuilder = TRUE;
11251 mono_loader_unlock ();
11252 mono_domain_unlock (domain);
11253 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11256 #endif
11258 /* enums are done right away */
11259 if (!klass->enumtype)
11260 ensure_runtime_vtable (klass);
11262 if (tb->subtypes) {
11263 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11264 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11265 mono_class_alloc_ext (klass);
11266 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)));
11270 klass->nested_classes_inited = TRUE;
11272 /* fields and object layout */
11273 if (klass->parent) {
11274 if (!klass->parent->size_inited)
11275 mono_class_init (klass->parent);
11276 klass->instance_size = klass->parent->instance_size;
11277 klass->sizes.class_size = 0;
11278 klass->min_align = klass->parent->min_align;
11279 /* if the type has no fields we won't call the field_setup
11280 * routine which sets up klass->has_references.
11282 klass->has_references |= klass->parent->has_references;
11283 } else {
11284 klass->instance_size = sizeof (MonoObject);
11285 klass->min_align = 1;
11288 /* FIXME: handle packing_size and instance_size */
11289 typebuilder_setup_fields (klass, &error);
11290 if (!mono_error_ok (&error))
11291 goto failure;
11292 typebuilder_setup_properties (klass, &error);
11293 if (!mono_error_ok (&error))
11294 goto failure;
11296 typebuilder_setup_events (klass, &error);
11297 if (!mono_error_ok (&error))
11298 goto failure;
11300 klass->wastypebuilder = TRUE;
11303 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11304 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11305 * we want to return normal System.MonoType objects, so clear these out from the cache.
11307 * Together with this we must ensure the contents of all instances to match the created type.
11309 if (domain->type_hash && klass->generic_container)
11310 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11312 mono_domain_unlock (domain);
11313 mono_loader_unlock ();
11315 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11316 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11317 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11320 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11321 g_assert (res != (MonoReflectionType*)tb);
11323 return res;
11325 failure:
11326 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11327 klass->wastypebuilder = TRUE;
11328 mono_domain_unlock (domain);
11329 mono_loader_unlock ();
11330 mono_error_raise_exception (&error);
11331 return NULL;
11334 void
11335 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11337 MonoGenericParamFull *param;
11338 MonoImage *image;
11339 MonoClass *pklass;
11341 MONO_ARCH_SAVE_REGS;
11343 param = g_new0 (MonoGenericParamFull, 1);
11345 if (gparam->mbuilder) {
11346 if (!gparam->mbuilder->generic_container) {
11347 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11348 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11349 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11350 gparam->mbuilder->generic_container->is_method = TRUE;
11352 * Cannot set owner.method, since the MonoMethod is not created yet.
11353 * Set the image field instead, so type_in_image () works.
11355 gparam->mbuilder->generic_container->image = klass->image;
11357 param->param.owner = gparam->mbuilder->generic_container;
11358 } else if (gparam->tbuilder) {
11359 if (!gparam->tbuilder->generic_container) {
11360 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11361 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11362 gparam->tbuilder->generic_container->owner.klass = klass;
11364 param->param.owner = gparam->tbuilder->generic_container;
11367 param->info.name = mono_string_to_utf8 (gparam->name);
11368 param->param.num = gparam->index;
11370 image = &gparam->tbuilder->module->dynamic_image->image;
11371 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11373 gparam->type.type = &pklass->byval_arg;
11375 mono_class_set_ref_info (pklass, gparam);
11376 mono_image_lock (image);
11377 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11378 mono_image_unlock (image);
11381 MonoArray *
11382 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11384 MonoReflectionModuleBuilder *module = sig->module;
11385 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11386 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11387 guint32 buflen, i;
11388 MonoArray *result;
11389 SigBuffer buf;
11391 check_array_for_usertypes (sig->arguments);
11393 sigbuffer_init (&buf, 32);
11395 sigbuffer_add_value (&buf, 0x07);
11396 sigbuffer_add_value (&buf, na);
11397 if (assembly != NULL){
11398 for (i = 0; i < na; ++i) {
11399 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11400 encode_reflection_type (assembly, type, &buf);
11404 buflen = buf.p - buf.buf;
11405 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11406 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11407 sigbuffer_free (&buf);
11409 return result;
11412 MonoArray *
11413 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11415 MonoDynamicImage *assembly = sig->module->dynamic_image;
11416 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11417 guint32 buflen, i;
11418 MonoArray *result;
11419 SigBuffer buf;
11421 check_array_for_usertypes (sig->arguments);
11423 sigbuffer_init (&buf, 32);
11425 sigbuffer_add_value (&buf, 0x06);
11426 for (i = 0; i < na; ++i) {
11427 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11428 encode_reflection_type (assembly, type, &buf);
11431 buflen = buf.p - buf.buf;
11432 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11433 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11434 sigbuffer_free (&buf);
11436 return result;
11439 void
11440 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11442 ReflectionMethodBuilder rmb;
11443 MonoMethodSignature *sig;
11444 MonoClass *klass;
11445 GSList *l;
11446 int i;
11448 sig = dynamic_method_to_signature (mb);
11450 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11453 * Resolve references.
11456 * Every second entry in the refs array is reserved for storing handle_class,
11457 * which is needed by the ldtoken implementation in the JIT.
11459 rmb.nrefs = mb->nrefs;
11460 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11461 for (i = 0; i < mb->nrefs; i += 2) {
11462 MonoClass *handle_class;
11463 gpointer ref;
11464 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11466 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11467 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11469 * The referenced DynamicMethod should already be created by the managed
11470 * code, except in the case of circular references. In that case, we store
11471 * method in the refs array, and fix it up later when the referenced
11472 * DynamicMethod is created.
11474 if (method->mhandle) {
11475 ref = method->mhandle;
11476 } else {
11477 /* FIXME: GC object stored in unmanaged memory */
11478 ref = method;
11480 /* FIXME: GC object stored in unmanaged memory */
11481 method->referenced_by = g_slist_append (method->referenced_by, mb);
11483 handle_class = mono_defaults.methodhandle_class;
11484 } else {
11485 MonoException *ex = NULL;
11486 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11487 if (!ref)
11488 ex = mono_get_exception_type_load (NULL, NULL);
11489 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11490 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11492 if (ex) {
11493 g_free (rmb.refs);
11494 mono_raise_exception (ex);
11495 return;
11499 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11500 rmb.refs [i + 1] = handle_class;
11503 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11505 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11507 /* Fix up refs entries pointing at us */
11508 for (l = mb->referenced_by; l; l = l->next) {
11509 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11510 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11511 gpointer *data;
11513 g_assert (method->mhandle);
11515 data = (gpointer*)wrapper->method_data;
11516 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11517 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11518 data [i + 1] = mb->mhandle;
11521 g_slist_free (mb->referenced_by);
11523 g_free (rmb.refs);
11525 /* ilgen is no longer needed */
11526 mb->ilgen = NULL;
11529 #endif /* DISABLE_REFLECTION_EMIT */
11531 void
11532 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11534 g_assert (mb);
11536 if (mb->mhandle)
11537 mono_runtime_free_method (
11538 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11543 * mono_reflection_is_valid_dynamic_token:
11545 * Returns TRUE if token is valid.
11548 gboolean
11549 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11551 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11554 #ifndef DISABLE_REFLECTION_EMIT
11557 * mono_reflection_lookup_dynamic_token:
11559 * Finish the Builder object pointed to by TOKEN and return the corresponding
11560 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11561 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11562 * mapping table.
11564 * LOCKING: Take the loader lock
11566 gpointer
11567 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11569 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11570 MonoObject *obj;
11571 MonoClass *klass;
11573 mono_loader_lock ();
11574 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11575 mono_loader_unlock ();
11576 if (!obj) {
11577 if (valid_token)
11578 g_error ("Could not find required dynamic token 0x%08x", token);
11579 else
11580 return NULL;
11583 if (!handle_class)
11584 handle_class = &klass;
11585 return resolve_object (image, obj, handle_class, context);
11588 MonoMethodSignature *
11589 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11591 MonoMethodSignature *sig;
11592 g_assert (image->dynamic);
11594 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11595 if (sig)
11596 return sig;
11598 return mono_method_signature (method);
11602 * ensure_complete_type:
11604 * Ensure that KLASS is completed if it is a dynamic type, or references
11605 * dynamic types.
11607 static void
11608 ensure_complete_type (MonoClass *klass)
11610 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11611 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11613 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11615 // Asserting here could break a lot of code
11616 //g_assert (klass->wastypebuilder);
11619 if (klass->generic_class) {
11620 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11621 int i;
11623 for (i = 0; i < inst->type_argc; ++i) {
11624 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11629 static gpointer
11630 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11632 gpointer result = NULL;
11634 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11635 result = mono_string_intern ((MonoString*)obj);
11636 *handle_class = mono_defaults.string_class;
11637 g_assert (result);
11638 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11639 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11640 MonoClass *mc = mono_class_from_mono_type (type);
11641 if (!mono_class_init (mc))
11642 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11644 if (context) {
11645 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11646 result = mono_class_from_mono_type (inflated);
11647 mono_metadata_free_type (inflated);
11648 } else {
11649 result = mono_class_from_mono_type (type);
11651 *handle_class = mono_defaults.typehandle_class;
11652 g_assert (result);
11653 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11654 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11655 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11656 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11657 result = ((MonoReflectionMethod*)obj)->method;
11658 if (context)
11659 result = mono_class_inflate_generic_method (result, context);
11660 *handle_class = mono_defaults.methodhandle_class;
11661 g_assert (result);
11662 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11663 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11664 result = mb->mhandle;
11665 if (!result) {
11666 /* Type is not yet created */
11667 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11669 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11672 * Hopefully this has been filled in by calling CreateType() on the
11673 * TypeBuilder.
11676 * TODO: This won't work if the application finishes another
11677 * TypeBuilder instance instead of this one.
11679 result = mb->mhandle;
11681 if (context)
11682 result = mono_class_inflate_generic_method (result, context);
11683 *handle_class = mono_defaults.methodhandle_class;
11684 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11685 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11687 result = cb->mhandle;
11688 if (!result) {
11689 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11691 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11692 result = cb->mhandle;
11694 if (context)
11695 result = mono_class_inflate_generic_method (result, context);
11696 *handle_class = mono_defaults.methodhandle_class;
11697 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11698 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11700 ensure_complete_type (field->parent);
11701 if (context) {
11702 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11703 MonoClass *class = mono_class_from_mono_type (inflated);
11704 MonoClassField *inflated_field;
11705 gpointer iter = NULL;
11706 mono_metadata_free_type (inflated);
11707 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11708 if (!strcmp (field->name, inflated_field->name))
11709 break;
11711 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11712 result = inflated_field;
11713 } else {
11714 result = field;
11716 *handle_class = mono_defaults.fieldhandle_class;
11717 g_assert (result);
11718 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11719 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11720 result = fb->handle;
11722 if (!result) {
11723 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11725 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11726 result = fb->handle;
11729 if (fb->handle && fb->handle->parent->generic_container) {
11730 MonoClass *klass = fb->handle->parent;
11731 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11732 MonoClass *inflated = mono_class_from_mono_type (type);
11734 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11735 g_assert (result);
11736 mono_metadata_free_type (type);
11738 *handle_class = mono_defaults.fieldhandle_class;
11739 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11740 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11741 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11742 MonoClass *klass;
11744 klass = type->data.klass;
11745 if (klass->wastypebuilder) {
11746 /* Already created */
11747 result = klass;
11749 else {
11750 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11751 result = type->data.klass;
11752 g_assert (result);
11754 *handle_class = mono_defaults.typehandle_class;
11755 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11756 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11757 MonoMethodSignature *sig;
11758 int nargs, i;
11760 if (helper->arguments)
11761 nargs = mono_array_length (helper->arguments);
11762 else
11763 nargs = 0;
11765 sig = mono_metadata_signature_alloc (image, nargs);
11766 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11767 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11769 if (helper->unmanaged_call_conv) { /* unmanaged */
11770 sig->call_convention = helper->unmanaged_call_conv - 1;
11771 sig->pinvoke = TRUE;
11772 } else if (helper->call_conv & 0x02) {
11773 sig->call_convention = MONO_CALL_VARARG;
11774 } else {
11775 sig->call_convention = MONO_CALL_DEFAULT;
11778 sig->param_count = nargs;
11779 /* TODO: Copy type ? */
11780 sig->ret = helper->return_type->type;
11781 for (i = 0; i < nargs; ++i)
11782 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11784 result = sig;
11785 *handle_class = NULL;
11786 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11787 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11788 /* Already created by the managed code */
11789 g_assert (method->mhandle);
11790 result = method->mhandle;
11791 *handle_class = mono_defaults.methodhandle_class;
11792 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11793 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11794 type = mono_class_inflate_generic_type (type, context);
11795 result = mono_class_from_mono_type (type);
11796 *handle_class = mono_defaults.typehandle_class;
11797 g_assert (result);
11798 mono_metadata_free_type (type);
11799 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11800 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11801 type = mono_class_inflate_generic_type (type, context);
11802 result = mono_class_from_mono_type (type);
11803 *handle_class = mono_defaults.typehandle_class;
11804 g_assert (result);
11805 mono_metadata_free_type (type);
11806 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11807 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11808 MonoClass *inflated;
11809 MonoType *type;
11810 MonoClassField *field;
11812 if (is_sre_field_builder (mono_object_class (f->fb)))
11813 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11814 else if (is_sr_mono_field (mono_object_class (f->fb)))
11815 field = ((MonoReflectionField*)f->fb)->field;
11816 else
11817 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)));
11819 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11820 inflated = mono_class_from_mono_type (type);
11822 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11823 ensure_complete_type (field->parent);
11824 g_assert (result);
11825 mono_metadata_free_type (type);
11826 *handle_class = mono_defaults.fieldhandle_class;
11827 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11828 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11829 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11830 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11831 MonoMethod *method;
11833 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11834 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11835 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11836 method = ((MonoReflectionMethod *)c->cb)->method;
11837 else
11838 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)));
11840 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11841 *handle_class = mono_defaults.methodhandle_class;
11842 mono_metadata_free_type (type);
11843 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11844 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11845 if (m->method_args) {
11846 result = mono_reflection_method_on_tb_inst_get_handle (m);
11847 if (context)
11848 result = mono_class_inflate_generic_method (result, context);
11849 } else {
11850 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11851 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11852 MonoMethod *method;
11854 if (is_sre_method_builder (mono_object_class (m->mb)))
11855 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11856 else if (is_sr_mono_method (mono_object_class (m->mb)))
11857 method = ((MonoReflectionMethod *)m->mb)->method;
11858 else
11859 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)));
11861 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11862 mono_metadata_free_type (type);
11864 *handle_class = mono_defaults.methodhandle_class;
11865 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11866 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11867 MonoType *mtype;
11868 MonoClass *klass;
11869 MonoMethod *method;
11870 gpointer iter;
11871 char *name;
11873 mtype = mono_reflection_type_get_handle (m->parent);
11874 klass = mono_class_from_mono_type (mtype);
11876 /* Find the method */
11878 name = mono_string_to_utf8 (m->name);
11879 iter = NULL;
11880 while ((method = mono_class_get_methods (klass, &iter))) {
11881 if (!strcmp (method->name, name))
11882 break;
11884 g_free (name);
11886 // FIXME:
11887 g_assert (method);
11888 // FIXME: Check parameters/return value etc. match
11890 result = method;
11891 *handle_class = mono_defaults.methodhandle_class;
11892 } else if (is_sre_array (mono_object_get_class(obj)) ||
11893 is_sre_byref (mono_object_get_class(obj)) ||
11894 is_sre_pointer (mono_object_get_class(obj))) {
11895 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11896 MonoType *type = mono_reflection_type_get_handle (ref_type);
11897 result = mono_class_from_mono_type (type);
11898 *handle_class = mono_defaults.typehandle_class;
11899 } else {
11900 g_print ("%s\n", obj->vtable->klass->name);
11901 g_assert_not_reached ();
11903 return result;
11906 #else /* DISABLE_REFLECTION_EMIT */
11908 MonoArray*
11909 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11911 g_assert_not_reached ();
11912 return NULL;
11915 void
11916 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11918 g_assert_not_reached ();
11921 void
11922 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11924 g_assert_not_reached ();
11927 void
11928 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11930 g_assert_not_reached ();
11933 void
11934 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11936 g_assert_not_reached ();
11939 void
11940 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11942 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11945 void
11946 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11948 g_assert_not_reached ();
11951 void
11952 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11954 g_assert_not_reached ();
11957 MonoReflectionModule *
11958 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11960 g_assert_not_reached ();
11961 return NULL;
11964 guint32
11965 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11967 g_assert_not_reached ();
11968 return 0;
11971 guint32
11972 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11974 g_assert_not_reached ();
11975 return 0;
11978 guint32
11979 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
11980 gboolean create_methodspec, gboolean register_token)
11982 g_assert_not_reached ();
11983 return 0;
11986 void
11987 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11991 void
11992 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
11993 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11994 MonoArray *events)
11996 g_assert_not_reached ();
11999 void
12000 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12002 *overrides = NULL;
12003 *num_overrides = 0;
12006 MonoReflectionEvent *
12007 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12009 g_assert_not_reached ();
12010 return NULL;
12013 MonoReflectionType*
12014 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12016 g_assert_not_reached ();
12017 return NULL;
12020 void
12021 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12023 g_assert_not_reached ();
12026 MonoArray *
12027 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12029 g_assert_not_reached ();
12030 return NULL;
12033 MonoArray *
12034 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12036 g_assert_not_reached ();
12037 return NULL;
12040 void
12041 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12045 gpointer
12046 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12048 return NULL;
12051 MonoType*
12052 mono_reflection_type_get_handle (MonoReflectionType* ref)
12054 if (!ref)
12055 return NULL;
12056 return ref->type;
12059 #endif /* DISABLE_REFLECTION_EMIT */
12061 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12062 const static guint32 declsec_flags_map[] = {
12063 0x00000000, /* empty */
12064 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12065 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12066 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12067 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12068 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12069 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12070 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12071 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12072 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12073 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12074 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12075 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12076 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12077 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12078 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12079 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12080 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12081 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12085 * Returns flags that includes all available security action associated to the handle.
12086 * @token: metadata token (either for a class or a method)
12087 * @image: image where resides the metadata.
12089 static guint32
12090 mono_declsec_get_flags (MonoImage *image, guint32 token)
12092 int index = mono_metadata_declsec_from_index (image, token);
12093 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12094 guint32 result = 0;
12095 guint32 action;
12096 int i;
12098 /* HasSecurity can be present for other, not specially encoded, attributes,
12099 e.g. SuppressUnmanagedCodeSecurityAttribute */
12100 if (index < 0)
12101 return 0;
12103 for (i = index; i < t->rows; i++) {
12104 guint32 cols [MONO_DECL_SECURITY_SIZE];
12106 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12107 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12108 break;
12110 action = cols [MONO_DECL_SECURITY_ACTION];
12111 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12112 result |= declsec_flags_map [action];
12113 } else {
12114 g_assert_not_reached ();
12117 return result;
12121 * Get the security actions (in the form of flags) associated with the specified method.
12123 * @method: The method for which we want the declarative security flags.
12124 * Return the declarative security flags for the method (only).
12126 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12127 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12129 guint32
12130 mono_declsec_flags_from_method (MonoMethod *method)
12132 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12133 /* FIXME: No cache (for the moment) */
12134 guint32 idx = mono_method_get_index (method);
12135 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12136 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12137 return mono_declsec_get_flags (method->klass->image, idx);
12139 return 0;
12143 * Get the security actions (in the form of flags) associated with the specified class.
12145 * @klass: The class for which we want the declarative security flags.
12146 * Return the declarative security flags for the class.
12148 * Note: We cache the flags inside the MonoClass structure as this will get
12149 * called very often (at least for each method).
12151 guint32
12152 mono_declsec_flags_from_class (MonoClass *klass)
12154 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12155 if (!klass->ext || !klass->ext->declsec_flags) {
12156 guint32 idx;
12158 idx = mono_metadata_token_index (klass->type_token);
12159 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12160 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12161 mono_loader_lock ();
12162 mono_class_alloc_ext (klass);
12163 mono_loader_unlock ();
12164 /* we cache the flags on classes */
12165 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12167 return klass->ext->declsec_flags;
12169 return 0;
12173 * Get the security actions (in the form of flags) associated with the specified assembly.
12175 * @assembly: The assembly for which we want the declarative security flags.
12176 * Return the declarative security flags for the assembly.
12178 guint32
12179 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12181 guint32 idx = 1; /* there is only one assembly */
12182 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12183 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12184 return mono_declsec_get_flags (assembly->image, idx);
12189 * Fill actions for the specific index (which may either be an encoded class token or
12190 * an encoded method token) from the metadata image.
12191 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12193 static MonoBoolean
12194 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12195 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12197 MonoBoolean result = FALSE;
12198 MonoTableInfo *t;
12199 guint32 cols [MONO_DECL_SECURITY_SIZE];
12200 int index = mono_metadata_declsec_from_index (image, token);
12201 int i;
12203 t = &image->tables [MONO_TABLE_DECLSECURITY];
12204 for (i = index; i < t->rows; i++) {
12205 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12207 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12208 return result;
12210 /* if present only replace (class) permissions with method permissions */
12211 /* if empty accept either class or method permissions */
12212 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12213 if (!actions->demand.blob) {
12214 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12215 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12216 actions->demand.blob = (char*) (blob + 2);
12217 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12218 result = TRUE;
12220 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12221 if (!actions->noncasdemand.blob) {
12222 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12223 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12224 actions->noncasdemand.blob = (char*) (blob + 2);
12225 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12226 result = TRUE;
12228 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12229 if (!actions->demandchoice.blob) {
12230 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12231 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12232 actions->demandchoice.blob = (char*) (blob + 2);
12233 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12234 result = TRUE;
12239 return result;
12242 static MonoBoolean
12243 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12244 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12246 guint32 idx = mono_metadata_token_index (klass->type_token);
12247 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12248 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12249 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12252 static MonoBoolean
12253 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12254 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12256 guint32 idx = mono_method_get_index (method);
12257 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12258 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12259 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12263 * Collect all actions (that requires to generate code in mini) assigned for
12264 * the specified method.
12265 * Note: Don't use the content of actions if the function return FALSE.
12267 MonoBoolean
12268 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12270 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12271 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12272 MonoBoolean result = FALSE;
12273 guint32 flags;
12275 /* quick exit if no declarative security is present in the metadata */
12276 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12277 return FALSE;
12279 /* we want the original as the wrapper is "free" of the security informations */
12280 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12281 method = mono_marshal_method_from_wrapper (method);
12282 if (!method)
12283 return FALSE;
12286 /* First we look for method-level attributes */
12287 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12288 mono_class_init (method->klass);
12289 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12291 result = mono_declsec_get_method_demands_params (method, demands,
12292 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12295 /* Here we use (or create) the class declarative cache to look for demands */
12296 flags = mono_declsec_flags_from_class (method->klass);
12297 if (flags & mask) {
12298 if (!result) {
12299 mono_class_init (method->klass);
12300 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12302 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12303 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12306 /* The boolean return value is used as a shortcut in case nothing needs to
12307 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12308 return result;
12313 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12315 * Note: Don't use the content of actions if the function return FALSE.
12317 MonoBoolean
12318 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12320 MonoBoolean result = FALSE;
12321 guint32 flags;
12323 /* quick exit if no declarative security is present in the metadata */
12324 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12325 return FALSE;
12327 /* we want the original as the wrapper is "free" of the security informations */
12328 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12329 method = mono_marshal_method_from_wrapper (method);
12330 if (!method)
12331 return FALSE;
12334 /* results are independant - zeroize both */
12335 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12336 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12338 /* First we look for method-level attributes */
12339 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12340 mono_class_init (method->klass);
12342 result = mono_declsec_get_method_demands_params (method, cmethod,
12343 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12346 /* Here we use (or create) the class declarative cache to look for demands */
12347 flags = mono_declsec_flags_from_class (method->klass);
12348 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12349 mono_class_init (method->klass);
12351 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12352 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12355 return result;
12359 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12361 * @klass The inherited class - this is the class that provides the security check (attributes)
12362 * @demans
12363 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12365 * Note: Don't use the content of actions if the function return FALSE.
12367 MonoBoolean
12368 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12370 MonoBoolean result = FALSE;
12371 guint32 flags;
12373 /* quick exit if no declarative security is present in the metadata */
12374 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12375 return FALSE;
12377 /* Here we use (or create) the class declarative cache to look for demands */
12378 flags = mono_declsec_flags_from_class (klass);
12379 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12380 mono_class_init (klass);
12381 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12383 result |= mono_declsec_get_class_demands_params (klass, demands,
12384 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12387 return result;
12391 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12393 * Note: Don't use the content of actions if the function return FALSE.
12395 MonoBoolean
12396 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12398 /* quick exit if no declarative security is present in the metadata */
12399 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12400 return FALSE;
12402 /* we want the original as the wrapper is "free" of the security informations */
12403 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12404 method = mono_marshal_method_from_wrapper (method);
12405 if (!method)
12406 return FALSE;
12409 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12410 mono_class_init (method->klass);
12411 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12413 return mono_declsec_get_method_demands_params (method, demands,
12414 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12416 return FALSE;
12420 static MonoBoolean
12421 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12423 guint32 cols [MONO_DECL_SECURITY_SIZE];
12424 MonoTableInfo *t;
12425 int i;
12427 int index = mono_metadata_declsec_from_index (image, token);
12428 if (index == -1)
12429 return FALSE;
12431 t = &image->tables [MONO_TABLE_DECLSECURITY];
12432 for (i = index; i < t->rows; i++) {
12433 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12435 /* shortcut - index are ordered */
12436 if (token != cols [MONO_DECL_SECURITY_PARENT])
12437 return FALSE;
12439 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12440 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12441 entry->blob = (char*) (metadata + 2);
12442 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12443 return TRUE;
12447 return FALSE;
12450 MonoBoolean
12451 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12453 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12454 guint32 idx = mono_method_get_index (method);
12455 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12456 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12457 return get_declsec_action (method->klass->image, idx, action, entry);
12459 return FALSE;
12462 MonoBoolean
12463 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12465 /* use cache */
12466 guint32 flags = mono_declsec_flags_from_class (klass);
12467 if (declsec_flags_map [action] & flags) {
12468 guint32 idx = mono_metadata_token_index (klass->type_token);
12469 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12470 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12471 return get_declsec_action (klass->image, idx, action, entry);
12473 return FALSE;
12476 MonoBoolean
12477 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12479 guint32 idx = 1; /* there is only one assembly */
12480 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12481 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12483 return get_declsec_action (assembly->image, idx, action, entry);
12486 gboolean
12487 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12489 MonoObject *res, *exc;
12490 void *params [1];
12491 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12492 static MonoMethod *method = NULL;
12494 if (!System_Reflection_Emit_TypeBuilder) {
12495 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12496 g_assert (System_Reflection_Emit_TypeBuilder);
12498 if (method == NULL) {
12499 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12500 g_assert (method);
12504 * The result of mono_type_get_object () might be a System.MonoType but we
12505 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12507 g_assert (mono_class_get_ref_info (klass));
12508 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12510 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12512 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12513 if (exc)
12514 return FALSE;
12515 else
12516 return *(MonoBoolean*)mono_object_unbox (res);