2 * sre.c: Routines for creating an image at runtime
3 * and related System.Reflection.Emit icalls
7 * Paolo Molaro (lupus@ximian.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 * Copyright 2011 Rodrigo Kumpera
12 * Copyright 2016 Microsoft
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
18 #include "mono/metadata/assembly.h"
19 #include "mono/metadata/debug-helpers.h"
20 #include "mono/metadata/dynamic-image-internals.h"
21 #include "mono/metadata/dynamic-stream-internals.h"
22 #include "mono/metadata/exception.h"
23 #include "mono/metadata/gc-internals.h"
24 #include "mono/metadata/mono-ptr-array.h"
25 #include "mono/metadata/object-internals.h"
26 #include "mono/metadata/profiler-private.h"
27 #include "mono/metadata/reflection-internals.h"
28 #include "mono/metadata/reflection-cache.h"
29 #include "mono/metadata/sre-internals.h"
30 #include "mono/metadata/custom-attrs-internals.h"
31 #include "mono/metadata/security-manager.h"
32 #include "mono/metadata/security-core-clr.h"
33 #include "mono/metadata/tabledefs.h"
34 #include "mono/metadata/tokentype.h"
36 #include "mono/utils/checked-build.h"
37 #include "mono/utils/mono-digest.h"
47 MonoReflectionILGen *ilgen;
48 MonoReflectionType *rtype;
49 MonoArray *parameters;
50 MonoArray *generic_params;
51 MonoGenericContainer *generic_container;
57 guint32 *table_idx; /* note: it's a pointer */
61 MonoBoolean init_locals;
62 MonoBoolean skip_visibility;
63 MonoArray *return_modreq;
64 MonoArray *return_modopt;
65 MonoArray *param_modreq;
66 MonoArray *param_modopt;
67 MonoArray *permissions;
72 int charset, extra_flags, native_cc;
73 MonoString *dll, *dllentry;
74 } ReflectionMethodBuilder;
76 struct _GenericParamTableEntry {
78 MonoReflectionGenericParam *gparam;
82 mono_sre_generic_param_table_entry_free (GenericParamTableEntry *entry)
84 mono_gc_deregister_root ((char*) &entry->gparam);
90 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
92 #ifndef DISABLE_REFLECTION_EMIT
93 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
94 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
95 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
96 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
97 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
98 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
99 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
100 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
101 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
102 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
103 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
106 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
107 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
108 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
109 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
110 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
111 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
112 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
113 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
114 static gboolean is_sre_array (MonoClass *klass);
115 static gboolean is_sre_byref (MonoClass *klass);
116 static gboolean is_sre_pointer (MonoClass *klass);
117 static gboolean is_sre_type_builder (MonoClass *klass);
118 static gboolean is_sre_method_builder (MonoClass *klass);
119 static gboolean is_sre_field_builder (MonoClass *klass);
120 static gboolean is_sr_mono_method (MonoClass *klass);
121 static gboolean is_sr_mono_generic_method (MonoClass *klass);
122 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
123 static gboolean is_sr_mono_field (MonoClass *klass);
125 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
126 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
127 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
129 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
130 static void init_type_builder_generics (MonoObject *type, MonoError *error);
132 #define TEXT_OFFSET 512
133 #define CLI_H_SIZE 136
134 #define FILE_ALIGN 512
135 #define VIRT_ALIGN 8192
136 #define START_TEXT_RVA 0x00002000
138 #define RESOLVE_TYPE(type, error) do { \
139 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
141 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
142 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
143 __type = mono_reflection_type_resolve_user_types (__type, error); \
144 if (mono_error_ok (error)) \
145 mono_array_set (arr, MonoReflectionType*, index, __type); \
148 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
150 static void mono_image_module_basic_init (MonoReflectionModuleBuilder *module);
153 mono_reflection_emit_init (void)
155 mono_dynamic_images_init ();
159 sigbuffer_init (SigBuffer *buf, int size)
161 MONO_REQ_GC_NEUTRAL_MODE;
163 buf->buf = (char *)g_malloc (size);
165 buf->end = buf->buf + size;
169 sigbuffer_make_room (SigBuffer *buf, int size)
171 MONO_REQ_GC_NEUTRAL_MODE;
173 if (buf->end - buf->p < size) {
174 int new_size = buf->end - buf->buf + size + 32;
175 char *p = (char *)g_realloc (buf->buf, new_size);
176 size = buf->p - buf->buf;
179 buf->end = buf->buf + new_size;
184 sigbuffer_add_value (SigBuffer *buf, guint32 val)
186 MONO_REQ_GC_NEUTRAL_MODE;
188 sigbuffer_make_room (buf, 6);
189 mono_metadata_encode_value (val, buf->p, &buf->p);
193 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
195 MONO_REQ_GC_NEUTRAL_MODE;
197 sigbuffer_make_room (buf, 1);
203 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
205 MONO_REQ_GC_NEUTRAL_MODE;
207 sigbuffer_make_room (buf, size);
208 memcpy (buf->p, p, size);
213 sigbuffer_free (SigBuffer *buf)
215 MONO_REQ_GC_NEUTRAL_MODE;
220 #ifndef DISABLE_REFLECTION_EMIT
224 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
228 image_g_malloc (MonoImage *image, guint size)
230 MONO_REQ_GC_NEUTRAL_MODE;
233 return mono_image_alloc (image, size);
235 return g_malloc (size);
237 #endif /* !DISABLE_REFLECTION_EMIT */
242 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
246 mono_image_g_malloc0 (MonoImage *image, guint size)
248 MONO_REQ_GC_NEUTRAL_MODE;
251 return mono_image_alloc0 (image, size);
253 return g_malloc0 (size);
258 * @image: a MonoImage
261 * If @image is NULL, free @ptr, otherwise do nothing.
264 image_g_free (MonoImage *image, gpointer ptr)
270 #ifndef DISABLE_REFLECTION_EMIT
272 image_strdup (MonoImage *image, const char *s)
274 MONO_REQ_GC_NEUTRAL_MODE;
277 return mono_image_strdup (image, s);
283 #define image_g_new(image,struct_type, n_structs) \
284 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
286 #define image_g_new0(image,struct_type, n_structs) \
287 ((struct_type *) mono_image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
291 alloc_table (MonoDynamicTable *table, guint nrows)
293 MONO_REQ_GC_NEUTRAL_MODE;
296 g_assert (table->columns);
297 if (nrows + 1 >= table->alloc_rows) {
298 while (nrows + 1 >= table->alloc_rows) {
299 if (table->alloc_rows == 0)
300 table->alloc_rows = 16;
302 table->alloc_rows *= 2;
305 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
310 string_heap_insert (MonoDynamicStream *sh, const char *str)
312 return mono_dynstream_insert_string (sh, str);
316 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
318 return mono_dynstream_insert_mstring (sh, str, error);
322 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
324 return mono_dynstream_add_data (stream, data, len);
328 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
330 return mono_dynstream_add_zero (stream, len);
334 stream_data_align (MonoDynamicStream *stream)
336 mono_dynstream_data_align (stream);
341 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
343 MONO_REQ_GC_NEUTRAL_MODE;
347 guint32 size = buf->p - buf->buf;
349 g_assert (size <= (buf->end - buf->buf));
350 mono_metadata_encode_value (size, b, &b);
351 return mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
356 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
357 * dest may be misaligned.
360 swap_with_size (char *dest, const char* val, int len, int nelem) {
361 MONO_REQ_GC_NEUTRAL_MODE;
362 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
365 for (elem = 0; elem < nelem; ++elem) {
391 g_assert_not_reached ();
397 memcpy (dest, val, len * nelem);
402 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
404 MONO_REQ_GC_UNSAFE_MODE;
408 guint32 idx = 0, len;
410 len = str->length * 2;
411 mono_metadata_encode_value (len, b, &b);
412 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
414 char *swapped = g_malloc (2 * mono_string_length (str));
415 const char *p = (const char*)mono_string_chars (str);
417 swap_with_size (swapped, p, 2, mono_string_length (str));
418 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
422 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
427 #ifndef DISABLE_REFLECTION_EMIT
429 default_class_from_mono_type (MonoType *type)
431 MONO_REQ_GC_NEUTRAL_MODE;
433 switch (type->type) {
434 case MONO_TYPE_OBJECT:
435 return mono_defaults.object_class;
437 return mono_defaults.void_class;
438 case MONO_TYPE_BOOLEAN:
439 return mono_defaults.boolean_class;
441 return mono_defaults.char_class;
443 return mono_defaults.sbyte_class;
445 return mono_defaults.byte_class;
447 return mono_defaults.int16_class;
449 return mono_defaults.uint16_class;
451 return mono_defaults.int32_class;
453 return mono_defaults.uint32_class;
455 return mono_defaults.int_class;
457 return mono_defaults.uint_class;
459 return mono_defaults.int64_class;
461 return mono_defaults.uint64_class;
463 return mono_defaults.single_class;
465 return mono_defaults.double_class;
466 case MONO_TYPE_STRING:
467 return mono_defaults.string_class;
469 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
470 g_assert_not_reached ();
478 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
480 MONO_REQ_GC_NEUTRAL_MODE;
483 MonoGenericInst *class_inst;
488 class_inst = gclass->context.class_inst;
490 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
491 klass = gclass->container_class;
492 sigbuffer_add_value (buf, klass->byval_arg.type);
493 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
495 sigbuffer_add_value (buf, class_inst->type_argc);
496 for (i = 0; i < class_inst->type_argc; ++i)
497 encode_type (assembly, class_inst->type_argv [i], buf);
502 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
504 MONO_REQ_GC_NEUTRAL_MODE;
507 g_assert_not_reached ();
512 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
516 case MONO_TYPE_BOOLEAN:
530 case MONO_TYPE_STRING:
531 case MONO_TYPE_OBJECT:
532 case MONO_TYPE_TYPEDBYREF:
533 sigbuffer_add_value (buf, type->type);
536 sigbuffer_add_value (buf, type->type);
537 encode_type (assembly, type->data.type, buf);
539 case MONO_TYPE_SZARRAY:
540 sigbuffer_add_value (buf, type->type);
541 encode_type (assembly, &type->data.klass->byval_arg, buf);
543 case MONO_TYPE_VALUETYPE:
544 case MONO_TYPE_CLASS: {
545 MonoClass *k = mono_class_from_mono_type (type);
547 if (k->generic_container) {
548 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
549 encode_generic_class (assembly, gclass, buf);
552 * Make sure we use the correct type.
554 sigbuffer_add_value (buf, k->byval_arg.type);
556 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
557 * otherwise two typerefs could point to the same type, leading to
558 * verification errors.
560 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
564 case MONO_TYPE_ARRAY:
565 sigbuffer_add_value (buf, type->type);
566 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
567 sigbuffer_add_value (buf, type->data.array->rank);
568 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
569 sigbuffer_add_value (buf, 0);
571 case MONO_TYPE_GENERICINST:
572 encode_generic_class (assembly, type->data.generic_class, buf);
576 sigbuffer_add_value (buf, type->type);
577 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
580 g_error ("need to encode type %x", type->type);
585 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
587 MONO_REQ_GC_UNSAFE_MODE;
589 mono_error_init (error);
592 sigbuffer_add_value (buf, MONO_TYPE_VOID);
596 MonoType *t = mono_reflection_type_get_handle (type, error);
597 return_if_nok (error);
598 encode_type (assembly, t, buf);
602 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
604 MONO_REQ_GC_UNSAFE_MODE;
608 mono_error_init (error);
611 for (i = 0; i < mono_array_length (modreq); ++i) {
612 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
613 return_if_nok (error);
614 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
615 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
619 for (i = 0; i < mono_array_length (modopt); ++i) {
620 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
621 return_if_nok (error);
622 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
623 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
628 #ifndef DISABLE_REFLECTION_EMIT
630 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
632 MONO_REQ_GC_UNSAFE_MODE;
636 guint32 nparams = sig->param_count;
642 sigbuffer_init (&buf, 32);
644 * FIXME: vararg, explicit_this, differenc call_conv values...
646 idx = sig->call_convention;
648 idx |= 0x20; /* hasthis */
649 if (sig->generic_param_count)
650 idx |= 0x10; /* generic */
651 sigbuffer_add_byte (&buf, idx);
652 if (sig->generic_param_count)
653 sigbuffer_add_value (&buf, sig->generic_param_count);
654 sigbuffer_add_value (&buf, nparams);
655 encode_type (assembly, sig->ret, &buf);
656 for (i = 0; i < nparams; ++i) {
657 if (i == sig->sentinelpos)
658 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
659 encode_type (assembly, sig->params [i], &buf);
661 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
662 sigbuffer_free (&buf);
668 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
670 MONO_REQ_GC_UNSAFE_MODE;
672 mono_error_init (error);
675 * FIXME: reuse code from method_encode_signature().
679 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
680 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
681 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
684 sigbuffer_init (&buf, 32);
685 /* LAMESPEC: all the call conv spec is foobared */
686 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
687 if (mb->call_conv & 2)
688 idx |= 0x5; /* vararg */
689 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
690 idx |= 0x20; /* hasthis */
692 idx |= 0x10; /* generic */
693 sigbuffer_add_byte (&buf, idx);
695 sigbuffer_add_value (&buf, ngparams);
696 sigbuffer_add_value (&buf, nparams + notypes);
697 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
700 encode_reflection_type (assembly, mb->rtype, &buf, error);
703 for (i = 0; i < nparams; ++i) {
704 MonoArray *modreq = NULL;
705 MonoArray *modopt = NULL;
706 MonoReflectionType *pt;
708 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
709 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
710 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
711 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
712 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
715 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
716 encode_reflection_type (assembly, pt, &buf, error);
721 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
722 for (i = 0; i < notypes; ++i) {
723 MonoReflectionType *pt;
725 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
726 encode_reflection_type (assembly, pt, &buf, error);
731 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
733 sigbuffer_free (&buf);
738 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
740 MONO_REQ_GC_UNSAFE_MODE;
742 mono_error_init (error);
744 MonoDynamicTable *table;
746 guint32 idx, sig_idx;
747 guint nl = mono_array_length (ilgen->locals);
751 sigbuffer_init (&buf, 32);
752 sigbuffer_add_value (&buf, 0x07);
753 sigbuffer_add_value (&buf, nl);
754 for (i = 0; i < nl; ++i) {
755 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
758 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
760 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
761 if (!is_ok (error)) {
762 sigbuffer_free (&buf);
766 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
767 sigbuffer_free (&buf);
769 if (assembly->standalonesig_cache == NULL)
770 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
771 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
775 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
776 idx = table->next_idx ++;
778 alloc_table (table, table->rows);
779 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
781 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
783 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
789 method_count_clauses (MonoReflectionILGen *ilgen)
791 MONO_REQ_GC_UNSAFE_MODE;
793 guint32 num_clauses = 0;
796 MonoILExceptionInfo *ex_info;
797 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
798 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
799 if (ex_info->handlers)
800 num_clauses += mono_array_length (ex_info->handlers);
808 #ifndef DISABLE_REFLECTION_EMIT
809 static MonoExceptionClause*
810 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
812 MONO_REQ_GC_UNSAFE_MODE;
814 mono_error_init (error);
816 MonoExceptionClause *clauses;
817 MonoExceptionClause *clause;
818 MonoILExceptionInfo *ex_info;
819 MonoILExceptionBlock *ex_block;
820 guint32 finally_start;
821 int i, j, clause_index;;
823 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
826 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
827 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
828 finally_start = ex_info->start + ex_info->len;
829 if (!ex_info->handlers)
831 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
832 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
833 clause = &(clauses [clause_index]);
835 clause->flags = ex_block->type;
836 clause->try_offset = ex_info->start;
838 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
839 clause->try_len = finally_start - ex_info->start;
841 clause->try_len = ex_info->len;
842 clause->handler_offset = ex_block->start;
843 clause->handler_len = ex_block->len;
844 if (ex_block->extype) {
845 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
847 if (!is_ok (error)) {
848 image_g_free (image, clauses);
851 clause->data.catch_class = mono_class_from_mono_type (extype);
853 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
854 clause->data.filter_offset = ex_block->filter_offset;
856 clause->data.filter_offset = 0;
858 finally_start = ex_block->start + ex_block->len;
866 #endif /* !DISABLE_REFLECTION_EMIT */
869 * method_encode_code:
871 * @assembly the assembly
872 * @mb the managed MethodBuilder
873 * @error set on error
875 * Note that the return value is not sensible if @error is set.
878 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
880 MONO_REQ_GC_UNSAFE_MODE;
886 gint32 num_locals = 0;
887 gint32 num_exception = 0;
890 char fat_header [12];
893 guint32 local_sig = 0;
894 guint32 header_size = 12;
897 mono_error_init (error);
899 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
900 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
904 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
906 code = mb->ilgen->code;
907 code_size = mb->ilgen->code_len;
908 max_stack = mb->ilgen->max_stack;
909 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
910 if (mb->ilgen->ex_handlers)
911 num_exception = method_count_clauses (mb->ilgen);
915 MonoError inner_error;
916 char *name = mono_string_to_utf8_checked (mb->name, &inner_error);
917 if (!is_ok (&inner_error)) {
918 name = g_strdup ("");
919 mono_error_cleanup (&inner_error);
921 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
922 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
928 code_size = mono_array_length (code);
929 max_stack = 8; /* we probably need to run a verifier on the code... */
932 stream_data_align (&assembly->code);
934 /* check for exceptions, maxstack, locals */
935 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
937 if (code_size < 64 && !(code_size & 1)) {
938 flags = (code_size << 2) | 0x2;
939 } else if (code_size < 32 && (code_size & 1)) {
940 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
944 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
945 /* add to the fixup todo list */
946 if (mb->ilgen && mb->ilgen->num_token_fixups)
947 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
948 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
949 return assembly->text_rva + idx;
953 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
954 return_val_if_nok (error, 0);
957 * FIXME: need to set also the header size in fat_flags.
958 * (and more sects and init locals flags)
962 fat_flags |= METHOD_HEADER_MORE_SECTS;
964 fat_flags |= METHOD_HEADER_INIT_LOCALS;
965 fat_header [0] = fat_flags;
966 fat_header [1] = (header_size / 4 ) << 4;
967 short_value = GUINT16_TO_LE (max_stack);
968 memcpy (fat_header + 2, &short_value, 2);
969 int_value = GUINT32_TO_LE (code_size);
970 memcpy (fat_header + 4, &int_value, 4);
971 int_value = GUINT32_TO_LE (local_sig);
972 memcpy (fat_header + 8, &int_value, 4);
973 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
974 /* add to the fixup todo list */
975 if (mb->ilgen && mb->ilgen->num_token_fixups)
976 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
978 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
980 unsigned char sheader [4];
981 MonoILExceptionInfo * ex_info;
982 MonoILExceptionBlock * ex_block;
985 stream_data_align (&assembly->code);
986 /* always use fat format for now */
987 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
988 num_exception *= 6 * sizeof (guint32);
989 num_exception += 4; /* include the size of the header */
990 sheader [1] = num_exception & 0xff;
991 sheader [2] = (num_exception >> 8) & 0xff;
992 sheader [3] = (num_exception >> 16) & 0xff;
993 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
994 /* fat header, so we are already aligned */
996 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
997 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
998 if (ex_info->handlers) {
999 int finally_start = ex_info->start + ex_info->len;
1000 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1002 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1004 val = GUINT32_TO_LE (ex_block->type);
1005 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1007 val = GUINT32_TO_LE (ex_info->start);
1008 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1009 /* need fault, too, probably */
1010 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1011 val = GUINT32_TO_LE (finally_start - ex_info->start);
1013 val = GUINT32_TO_LE (ex_info->len);
1014 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1015 /* handler offset */
1016 val = GUINT32_TO_LE (ex_block->start);
1017 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1019 val = GUINT32_TO_LE (ex_block->len);
1020 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1021 finally_start = ex_block->start + ex_block->len;
1022 if (ex_block->extype) {
1023 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1024 return_val_if_nok (error, 0);
1026 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1028 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1029 val = ex_block->filter_offset;
1033 val = GUINT32_TO_LE (val);
1034 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1035 /*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",
1036 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);*/
1039 g_error ("No clauses for ex info block %d", i);
1043 return assembly->text_rva + idx;
1047 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1049 MONO_REQ_GC_NEUTRAL_MODE;
1052 MonoDynamicTable *table;
1055 table = &assembly->tables [table_idx];
1057 g_assert (col < table->columns);
1059 values = table->values + table->columns;
1060 for (i = 1; i <= table->rows; ++i) {
1061 if (values [col] == token)
1063 values += table->columns;
1068 #ifndef DISABLE_REFLECTION_EMIT
1070 * LOCKING: Acquires the loader lock.
1073 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1075 MONO_REQ_GC_UNSAFE_MODE;
1077 MonoCustomAttrInfo *ainfo, *tmp;
1079 if (!cattrs || !mono_array_length (cattrs))
1082 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1084 mono_loader_lock ();
1085 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1087 mono_custom_attrs_free (tmp);
1088 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1089 mono_loader_unlock ();
1095 * idx is the table index of the object
1096 * type is one of MONO_CUSTOM_ATTR_*
1099 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1101 MONO_REQ_GC_UNSAFE_MODE;
1103 MonoDynamicTable *table;
1104 MonoReflectionCustomAttr *cattr;
1106 guint32 count, i, token;
1108 char *p = blob_size;
1110 mono_error_init (error);
1112 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1115 count = mono_array_length (cattrs);
1116 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1117 table->rows += count;
1118 alloc_table (table, table->rows);
1119 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1120 idx <<= MONO_CUSTOM_ATTR_BITS;
1122 for (i = 0; i < count; ++i) {
1123 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1124 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1125 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1126 if (!mono_error_ok (error)) goto fail;
1127 type = mono_metadata_token_index (token);
1128 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1129 switch (mono_metadata_token_table (token)) {
1130 case MONO_TABLE_METHOD:
1131 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1133 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1134 * method, not the one returned by mono_image_create_token ().
1136 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1138 case MONO_TABLE_MEMBERREF:
1139 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1142 g_warning ("got wrong token in custom attr");
1145 values [MONO_CUSTOM_ATTR_TYPE] = type;
1147 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1148 values [MONO_CUSTOM_ATTR_VALUE] = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, p - blob_size,
1149 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1150 values += MONO_CUSTOM_ATTR_SIZE;
1161 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1163 MONO_REQ_GC_UNSAFE_MODE;
1165 MonoDynamicTable *table;
1167 guint32 count, i, idx;
1168 MonoReflectionPermissionSet *perm;
1173 count = mono_array_length (permissions);
1174 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1175 table->rows += count;
1176 alloc_table (table, table->rows);
1178 for (i = 0; i < mono_array_length (permissions); ++i) {
1179 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1181 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1183 idx = mono_metadata_token_index (parent_token);
1184 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1185 switch (mono_metadata_token_table (parent_token)) {
1186 case MONO_TABLE_TYPEDEF:
1187 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1189 case MONO_TABLE_METHOD:
1190 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1192 case MONO_TABLE_ASSEMBLY:
1193 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1196 g_assert_not_reached ();
1199 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1200 values [MONO_DECL_SECURITY_PARENT] = idx;
1201 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1208 * Fill in the MethodDef and ParamDef tables for a method.
1209 * This is used for both normal methods and constructors.
1212 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1214 MONO_REQ_GC_UNSAFE_MODE;
1216 MonoDynamicTable *table;
1220 mono_error_init (error);
1222 /* room in this table is already allocated */
1223 table = &assembly->tables [MONO_TABLE_METHOD];
1224 *mb->table_idx = table->next_idx ++;
1225 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1226 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1227 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
1228 return_val_if_nok (error, FALSE);
1229 values [MONO_METHOD_FLAGS] = mb->attrs;
1230 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1231 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1232 return_val_if_nok (error, FALSE);
1233 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1234 return_val_if_nok (error, FALSE);
1236 table = &assembly->tables [MONO_TABLE_PARAM];
1237 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1239 mono_image_add_decl_security (assembly,
1240 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1243 MonoDynamicTable *mtable;
1246 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1247 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1250 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1251 if (mono_array_get (mb->pinfo, gpointer, i))
1254 table->rows += count;
1255 alloc_table (table, table->rows);
1256 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1257 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1258 MonoReflectionParamBuilder *pb;
1259 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1260 values [MONO_PARAM_FLAGS] = pb->attrs;
1261 values [MONO_PARAM_SEQUENCE] = i;
1262 if (pb->name != NULL) {
1263 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
1264 return_val_if_nok (error, FALSE);
1266 values [MONO_PARAM_NAME] = 0;
1268 values += MONO_PARAM_SIZE;
1269 if (pb->marshal_info) {
1271 alloc_table (mtable, mtable->rows);
1272 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1273 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1274 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1275 return_val_if_nok (error, FALSE);
1277 pb->table_idx = table->next_idx++;
1278 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1279 guint32 field_type = 0;
1280 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1282 alloc_table (mtable, mtable->rows);
1283 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1284 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1285 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1286 mvalues [MONO_CONSTANT_TYPE] = field_type;
1287 mvalues [MONO_CONSTANT_PADDING] = 0;
1296 #ifndef DISABLE_REFLECTION_EMIT
1298 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1300 MONO_REQ_GC_UNSAFE_MODE;
1302 mono_error_init (error);
1303 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1305 rmb->ilgen = mb->ilgen;
1306 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1307 return_val_if_nok (error, FALSE);
1308 rmb->parameters = mb->parameters;
1309 rmb->generic_params = mb->generic_params;
1310 rmb->generic_container = mb->generic_container;
1311 rmb->opt_types = NULL;
1312 rmb->pinfo = mb->pinfo;
1313 rmb->attrs = mb->attrs;
1314 rmb->iattrs = mb->iattrs;
1315 rmb->call_conv = mb->call_conv;
1316 rmb->code = mb->code;
1317 rmb->type = mb->type;
1318 rmb->name = mb->name;
1319 rmb->table_idx = &mb->table_idx;
1320 rmb->init_locals = mb->init_locals;
1321 rmb->skip_visibility = FALSE;
1322 rmb->return_modreq = mb->return_modreq;
1323 rmb->return_modopt = mb->return_modopt;
1324 rmb->param_modreq = mb->param_modreq;
1325 rmb->param_modopt = mb->param_modopt;
1326 rmb->permissions = mb->permissions;
1327 rmb->mhandle = mb->mhandle;
1332 rmb->charset = mb->charset;
1333 rmb->extra_flags = mb->extra_flags;
1334 rmb->native_cc = mb->native_cc;
1335 rmb->dllentry = mb->dllentry;
1343 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1345 MONO_REQ_GC_UNSAFE_MODE;
1347 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1349 mono_error_init (error);
1351 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1353 rmb->ilgen = mb->ilgen;
1354 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1355 return_val_if_nok (error, FALSE);
1356 rmb->parameters = mb->parameters;
1357 rmb->generic_params = NULL;
1358 rmb->generic_container = NULL;
1359 rmb->opt_types = NULL;
1360 rmb->pinfo = mb->pinfo;
1361 rmb->attrs = mb->attrs;
1362 rmb->iattrs = mb->iattrs;
1363 rmb->call_conv = mb->call_conv;
1365 rmb->type = mb->type;
1366 rmb->name = mono_string_new (mono_domain_get (), name);
1367 rmb->table_idx = &mb->table_idx;
1368 rmb->init_locals = mb->init_locals;
1369 rmb->skip_visibility = FALSE;
1370 rmb->return_modreq = NULL;
1371 rmb->return_modopt = NULL;
1372 rmb->param_modreq = mb->param_modreq;
1373 rmb->param_modopt = mb->param_modopt;
1374 rmb->permissions = mb->permissions;
1375 rmb->mhandle = mb->mhandle;
1383 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1385 MONO_REQ_GC_UNSAFE_MODE;
1387 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1389 rmb->ilgen = mb->ilgen;
1390 rmb->rtype = mb->rtype;
1391 rmb->parameters = mb->parameters;
1392 rmb->generic_params = NULL;
1393 rmb->generic_container = NULL;
1394 rmb->opt_types = NULL;
1396 rmb->attrs = mb->attrs;
1398 rmb->call_conv = mb->call_conv;
1400 rmb->type = (MonoObject *) mb->owner;
1401 rmb->name = mb->name;
1402 rmb->table_idx = NULL;
1403 rmb->init_locals = mb->init_locals;
1404 rmb->skip_visibility = mb->skip_visibility;
1405 rmb->return_modreq = NULL;
1406 rmb->return_modopt = NULL;
1407 rmb->param_modreq = NULL;
1408 rmb->param_modopt = NULL;
1409 rmb->permissions = NULL;
1410 rmb->mhandle = mb->mhandle;
1417 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1419 MONO_REQ_GC_UNSAFE_MODE;
1421 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1422 MonoDynamicTable *table;
1425 MonoReflectionMethod *m;
1428 mono_error_init (error);
1430 if (!mb->override_methods)
1433 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1434 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1436 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1438 alloc_table (table, table->rows);
1439 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1440 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1441 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1443 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1444 return_val_if_nok (error, FALSE);
1446 switch (mono_metadata_token_table (tok)) {
1447 case MONO_TABLE_MEMBERREF:
1448 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1450 case MONO_TABLE_METHOD:
1451 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1454 g_assert_not_reached ();
1456 values [MONO_METHODIMPL_DECLARATION] = tok;
1462 #ifndef DISABLE_REFLECTION_EMIT
1464 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1466 MONO_REQ_GC_UNSAFE_MODE;
1468 MonoDynamicTable *table;
1470 ReflectionMethodBuilder rmb;
1473 mono_error_init (error);
1475 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1476 !mono_image_basic_method (&rmb, assembly, error))
1479 mb->table_idx = *rmb.table_idx;
1481 if (mb->dll) { /* It's a P/Invoke method */
1483 /* map CharSet values to on-disk values */
1484 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1485 int extra_flags = mb->extra_flags;
1486 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1488 alloc_table (table, table->rows);
1489 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1491 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1492 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1494 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry, error);
1495 return_val_if_nok (error, FALSE);
1497 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
1498 return_val_if_nok (error, FALSE);
1500 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll, error);
1501 return_val_if_nok (error, FALSE);
1502 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1503 table = &assembly->tables [MONO_TABLE_MODULEREF];
1505 alloc_table (table, table->rows);
1506 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1507 values [MONO_IMPLMAP_SCOPE] = table->rows;
1511 if (mb->generic_params) {
1512 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1513 table->rows += mono_array_length (mb->generic_params);
1514 alloc_table (table, table->rows);
1515 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1516 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1518 mono_image_get_generic_param_info (
1519 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1527 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1529 MONO_REQ_GC_UNSAFE_MODE;
1531 ReflectionMethodBuilder rmb;
1533 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1536 if (!mono_image_basic_method (&rmb, assembly, error))
1539 mb->table_idx = *rmb.table_idx;
1546 type_get_fully_qualified_name (MonoType *type)
1548 MONO_REQ_GC_NEUTRAL_MODE;
1550 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1554 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1556 MONO_REQ_GC_UNSAFE_MODE;
1561 klass = mono_class_from_mono_type (type);
1563 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1564 ta = klass->image->assembly;
1565 if (assembly_is_dynamic (ta) || (ta == ass)) {
1566 if (klass->generic_class || klass->generic_container)
1567 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1568 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1570 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1573 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1576 #ifndef DISABLE_REFLECTION_EMIT
1577 /*field_image is the image to which the eventual custom mods have been encoded against*/
1579 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1581 MONO_REQ_GC_NEUTRAL_MODE;
1584 guint32 idx, i, token;
1586 if (!assembly->save)
1589 sigbuffer_init (&buf, 32);
1591 sigbuffer_add_value (&buf, 0x06);
1592 /* encode custom attributes before the type */
1593 if (type->num_mods) {
1594 for (i = 0; i < type->num_mods; ++i) {
1597 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1598 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1600 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1602 token = type->modifiers [i].token;
1605 if (type->modifiers [i].required)
1606 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1608 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1610 sigbuffer_add_value (&buf, token);
1613 encode_type (assembly, type, &buf);
1614 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1615 sigbuffer_free (&buf);
1621 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
1623 MONO_REQ_GC_UNSAFE_MODE;
1625 mono_error_init (error);
1629 guint32 typespec = 0;
1633 init_type_builder_generics (fb->type, error);
1634 return_val_if_nok (error, 0);
1636 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
1637 return_val_if_nok (error, 0);
1638 klass = mono_class_from_mono_type (type);
1640 sigbuffer_init (&buf, 32);
1642 sigbuffer_add_value (&buf, 0x06);
1643 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
1646 /* encode custom attributes before the type */
1648 if (klass->generic_container)
1649 typespec = create_typespec (assembly, type);
1652 MonoGenericClass *gclass;
1653 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
1654 encode_generic_class (assembly, gclass, &buf);
1656 encode_type (assembly, type, &buf);
1658 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1659 sigbuffer_free (&buf);
1662 sigbuffer_free (&buf);
1667 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
1669 MONO_REQ_GC_UNSAFE_MODE;
1671 char blob_size [64];
1672 char *b = blob_size;
1675 guint32 idx = 0, len = 0, dummy = 0;
1677 buf = (char *)g_malloc (64);
1679 *ret_type = MONO_TYPE_CLASS;
1681 box_val = (char*)&dummy;
1683 box_val = ((char*)val) + sizeof (MonoObject);
1684 *ret_type = val->vtable->klass->byval_arg.type;
1687 switch (*ret_type) {
1688 case MONO_TYPE_BOOLEAN:
1693 case MONO_TYPE_CHAR:
1710 case MONO_TYPE_VALUETYPE: {
1711 MonoClass *klass = val->vtable->klass;
1713 if (klass->enumtype) {
1714 *ret_type = mono_class_enum_basetype (klass)->type;
1716 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1719 g_error ("we can't encode valuetypes, we should have never reached this line");
1722 case MONO_TYPE_CLASS:
1724 case MONO_TYPE_STRING: {
1725 MonoString *str = (MonoString*)val;
1726 /* there is no signature */
1727 len = str->length * 2;
1728 mono_metadata_encode_value (len, b, &b);
1729 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1731 char *swapped = g_malloc (2 * mono_string_length (str));
1732 const char *p = (const char*)mono_string_chars (str);
1734 swap_with_size (swapped, p, 2, mono_string_length (str));
1735 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1739 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1745 case MONO_TYPE_GENERICINST:
1746 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1749 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1752 /* there is no signature */
1753 mono_metadata_encode_value (len, b, &b);
1754 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1755 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1756 swap_with_size (blob_size, box_val, len, 1);
1757 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1759 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1767 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
1769 MONO_REQ_GC_UNSAFE_MODE;
1771 mono_error_init (error);
1777 sigbuffer_init (&buf, 32);
1779 sigbuffer_add_value (&buf, minfo->type);
1781 switch (minfo->type) {
1782 case MONO_NATIVE_BYVALTSTR:
1783 case MONO_NATIVE_BYVALARRAY:
1784 sigbuffer_add_value (&buf, minfo->count);
1786 case MONO_NATIVE_LPARRAY:
1787 if (minfo->eltype || minfo->has_size) {
1788 sigbuffer_add_value (&buf, minfo->eltype);
1789 if (minfo->has_size) {
1790 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1791 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1793 /* LAMESPEC: ElemMult is undocumented */
1794 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1798 case MONO_NATIVE_SAFEARRAY:
1800 sigbuffer_add_value (&buf, minfo->eltype);
1802 case MONO_NATIVE_CUSTOM:
1804 str = mono_string_to_utf8_checked (minfo->guid, error);
1805 if (!is_ok (error)) {
1806 sigbuffer_free (&buf);
1810 sigbuffer_add_value (&buf, len);
1811 sigbuffer_add_mem (&buf, str, len);
1814 sigbuffer_add_value (&buf, 0);
1816 /* native type name */
1817 sigbuffer_add_value (&buf, 0);
1818 /* custom marshaler type name */
1819 if (minfo->marshaltype || minfo->marshaltyperef) {
1820 if (minfo->marshaltyperef) {
1821 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
1822 if (!is_ok (error)) {
1823 sigbuffer_free (&buf);
1826 str = type_get_fully_qualified_name (marshaltype);
1828 str = mono_string_to_utf8_checked (minfo->marshaltype, error);
1829 if (!is_ok (error)) {
1830 sigbuffer_free (&buf);
1835 sigbuffer_add_value (&buf, len);
1836 sigbuffer_add_mem (&buf, str, len);
1839 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1840 sigbuffer_add_value (&buf, 0);
1842 if (minfo->mcookie) {
1843 str = mono_string_to_utf8_checked (minfo->mcookie, error);
1844 if (!is_ok (error)) {
1845 sigbuffer_free (&buf);
1849 sigbuffer_add_value (&buf, len);
1850 sigbuffer_add_mem (&buf, str, len);
1853 sigbuffer_add_value (&buf, 0);
1859 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1860 sigbuffer_free (&buf);
1865 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
1867 MONO_REQ_GC_UNSAFE_MODE;
1869 mono_error_init (error);
1871 MonoDynamicTable *table;
1874 /* maybe this fixup should be done in the C# code */
1875 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1876 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1877 table = &assembly->tables [MONO_TABLE_FIELD];
1878 fb->table_idx = table->next_idx ++;
1879 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1880 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1881 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name, error);
1882 return_if_nok (error);
1883 values [MONO_FIELD_FLAGS] = fb->attrs;
1884 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
1885 return_if_nok (error);
1888 if (fb->offset != -1) {
1889 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1891 alloc_table (table, table->rows);
1892 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1893 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1894 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1896 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1897 MonoTypeEnum field_type = (MonoTypeEnum)0;
1898 table = &assembly->tables [MONO_TABLE_CONSTANT];
1900 alloc_table (table, table->rows);
1901 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1902 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1903 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1904 values [MONO_CONSTANT_TYPE] = field_type;
1905 values [MONO_CONSTANT_PADDING] = 0;
1907 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1909 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1911 alloc_table (table, table->rows);
1912 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1913 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1915 * We store it in the code section because it's simpler for now.
1918 if (mono_array_length (fb->rva_data) >= 10)
1919 stream_data_align (&assembly->code);
1920 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1922 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1923 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1925 if (fb->marshal_info) {
1926 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1928 alloc_table (table, table->rows);
1929 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1930 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1931 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
1932 return_if_nok (error);
1937 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
1939 MONO_REQ_GC_UNSAFE_MODE;
1941 mono_error_init (error);
1944 guint32 nparams = 0;
1945 MonoReflectionMethodBuilder *mb = fb->get_method;
1946 MonoReflectionMethodBuilder *smb = fb->set_method;
1949 if (mb && mb->parameters)
1950 nparams = mono_array_length (mb->parameters);
1951 if (!mb && smb && smb->parameters)
1952 nparams = mono_array_length (smb->parameters) - 1;
1953 sigbuffer_init (&buf, 32);
1954 if (fb->call_conv & 0x20)
1955 sigbuffer_add_byte (&buf, 0x28);
1957 sigbuffer_add_byte (&buf, 0x08);
1958 sigbuffer_add_value (&buf, nparams);
1960 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
1963 for (i = 0; i < nparams; ++i) {
1964 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1965 encode_reflection_type (assembly, pt, &buf, error);
1969 } else if (smb && smb->parameters) {
1970 /* the property type is the last param */
1971 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
1975 for (i = 0; i < nparams; ++i) {
1976 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1977 encode_reflection_type (assembly, pt, &buf, error);
1982 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
1987 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1988 sigbuffer_free (&buf);
1991 sigbuffer_free (&buf);
1996 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
1998 MONO_REQ_GC_UNSAFE_MODE;
2000 mono_error_init (error);
2002 MonoDynamicTable *table;
2004 guint num_methods = 0;
2008 * we need to set things in the following tables:
2009 * PROPERTYMAP (info already filled in _get_type_info ())
2010 * PROPERTY (rows already preallocated in _get_type_info ())
2011 * METHOD (method info already done with the generic method code)
2015 table = &assembly->tables [MONO_TABLE_PROPERTY];
2016 pb->table_idx = table->next_idx ++;
2017 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2018 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
2019 return_if_nok (error);
2020 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2021 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2022 return_if_nok (error);
2025 /* FIXME: we still don't handle 'other' methods */
2026 if (pb->get_method) num_methods ++;
2027 if (pb->set_method) num_methods ++;
2029 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2030 table->rows += num_methods;
2031 alloc_table (table, table->rows);
2033 if (pb->get_method) {
2034 semaidx = table->next_idx ++;
2035 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2036 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2037 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2038 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2040 if (pb->set_method) {
2041 semaidx = table->next_idx ++;
2042 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2043 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2044 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2045 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2047 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2048 MonoTypeEnum field_type = (MonoTypeEnum)0;
2049 table = &assembly->tables [MONO_TABLE_CONSTANT];
2051 alloc_table (table, table->rows);
2052 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2053 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2054 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2055 values [MONO_CONSTANT_TYPE] = field_type;
2056 values [MONO_CONSTANT_PADDING] = 0;
2061 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2063 MONO_REQ_GC_UNSAFE_MODE;
2065 MonoDynamicTable *table;
2067 guint num_methods = 0;
2071 * we need to set things in the following tables:
2072 * EVENTMAP (info already filled in _get_type_info ())
2073 * EVENT (rows already preallocated in _get_type_info ())
2074 * METHOD (method info already done with the generic method code)
2077 table = &assembly->tables [MONO_TABLE_EVENT];
2078 eb->table_idx = table->next_idx ++;
2079 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2080 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name, error);
2081 return_if_nok (error);
2082 values [MONO_EVENT_FLAGS] = eb->attrs;
2083 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2084 return_if_nok (error);
2085 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2088 * FIXME: we still don't handle 'other' methods
2090 if (eb->add_method) num_methods ++;
2091 if (eb->remove_method) num_methods ++;
2092 if (eb->raise_method) num_methods ++;
2094 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2095 table->rows += num_methods;
2096 alloc_table (table, table->rows);
2098 if (eb->add_method) {
2099 semaidx = table->next_idx ++;
2100 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2101 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2102 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2103 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2105 if (eb->remove_method) {
2106 semaidx = table->next_idx ++;
2107 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2108 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2109 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2110 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2112 if (eb->raise_method) {
2113 semaidx = table->next_idx ++;
2114 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2115 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2116 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2117 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2122 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2124 MONO_REQ_GC_UNSAFE_MODE;
2126 mono_error_init (error);
2128 MonoDynamicTable *table;
2129 guint32 num_constraints, i;
2133 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2134 num_constraints = gparam->iface_constraints ?
2135 mono_array_length (gparam->iface_constraints) : 0;
2136 table->rows += num_constraints;
2137 if (gparam->base_type)
2139 alloc_table (table, table->rows);
2141 if (gparam->base_type) {
2142 table_idx = table->next_idx ++;
2143 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2145 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2146 return_if_nok (error);
2147 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2148 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2151 for (i = 0; i < num_constraints; i++) {
2152 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2153 gparam->iface_constraints, gpointer, i);
2155 table_idx = table->next_idx ++;
2156 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2158 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2159 return_if_nok (error);
2161 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2162 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2167 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2169 MONO_REQ_GC_UNSAFE_MODE;
2171 GenericParamTableEntry *entry;
2174 * The GenericParam table must be sorted according to the `owner' field.
2175 * We need to do this sorting prior to writing the GenericParamConstraint
2176 * table, since we have to use the final GenericParam table indices there
2177 * and they must also be sorted.
2180 entry = g_new0 (GenericParamTableEntry, 1);
2181 entry->owner = owner;
2182 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2183 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2184 entry->gparam = gparam;
2186 g_ptr_array_add (assembly->gen_params, entry);
2190 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2192 MONO_REQ_GC_UNSAFE_MODE;
2194 MonoDynamicTable *table;
2195 MonoGenericParam *param;
2199 mono_error_init (error);
2201 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2202 table_idx = table->next_idx ++;
2203 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2205 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2206 return_val_if_nok (error, FALSE);
2208 param = gparam_type->data.generic_param;
2210 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2211 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2212 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2213 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2215 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2218 encode_constraints (entry->gparam, table_idx, assembly, error);
2219 return_val_if_nok (error, FALSE);
2225 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2227 MONO_REQ_GC_UNSAFE_MODE;
2229 MonoDynamicTable *table;
2232 guint32 cols [MONO_ASSEMBLY_SIZE];
2236 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2239 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2240 table = &assembly->tables [MONO_TABLE_MODULEREF];
2241 token = table->next_idx ++;
2243 alloc_table (table, table->rows);
2244 values = table->values + token * MONO_MODULEREF_SIZE;
2245 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2247 token <<= MONO_RESOLUTION_SCOPE_BITS;
2248 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2249 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2254 if (assembly_is_dynamic (image->assembly))
2256 memset (cols, 0, sizeof (cols));
2258 /* image->assembly->image is the manifest module */
2259 image = image->assembly->image;
2260 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2263 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2264 token = table->next_idx ++;
2266 alloc_table (table, table->rows);
2267 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2268 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2269 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2270 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2271 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2272 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2273 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2274 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2275 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2277 if (strcmp ("", image->assembly->aname.culture)) {
2278 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2279 image->assembly->aname.culture);
2282 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2283 guchar pubtoken [9];
2285 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2286 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2288 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2290 token <<= MONO_RESOLUTION_SCOPE_BITS;
2291 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2292 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2297 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2299 MONO_REQ_GC_NEUTRAL_MODE;
2301 MonoDynamicTable *table;
2306 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2309 sigbuffer_init (&buf, 32);
2310 switch (type->type) {
2311 case MONO_TYPE_FNPTR:
2313 case MONO_TYPE_SZARRAY:
2314 case MONO_TYPE_ARRAY:
2316 case MONO_TYPE_MVAR:
2317 case MONO_TYPE_GENERICINST:
2318 encode_type (assembly, type, &buf);
2320 case MONO_TYPE_CLASS:
2321 case MONO_TYPE_VALUETYPE: {
2322 MonoClass *k = mono_class_from_mono_type (type);
2323 if (!k || !k->generic_container) {
2324 sigbuffer_free (&buf);
2327 encode_type (assembly, type, &buf);
2331 sigbuffer_free (&buf);
2335 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2336 if (assembly->save) {
2337 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2338 alloc_table (table, table->rows + 1);
2339 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2340 values [MONO_TYPESPEC_SIGNATURE] = token;
2342 sigbuffer_free (&buf);
2344 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2345 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2351 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2353 MONO_REQ_GC_UNSAFE_MODE;
2355 MonoDynamicTable *table;
2357 guint32 token, scope, enclosing;
2360 /* if the type requires a typespec, we must try that first*/
2361 if (try_typespec && (token = create_typespec (assembly, type)))
2363 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2366 klass = mono_class_from_mono_type (type);
2368 klass = mono_class_from_mono_type (type);
2371 * If it's in the same module and not a generic type parameter:
2373 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2374 (type->type != MONO_TYPE_MVAR)) {
2375 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2376 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2377 mono_dynamic_image_register_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2381 if (klass->nested_in) {
2382 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2383 /* get the typeref idx of the enclosing type */
2384 enclosing >>= MONO_TYPEDEFORREF_BITS;
2385 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2387 scope = resolution_scope_from_image (assembly, klass->image);
2389 table = &assembly->tables [MONO_TABLE_TYPEREF];
2390 if (assembly->save) {
2391 alloc_table (table, table->rows + 1);
2392 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2393 values [MONO_TYPEREF_SCOPE] = scope;
2394 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2395 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2397 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2398 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2400 mono_dynamic_image_register_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2405 * Despite the name, we handle also TypeSpec (with the above helper).
2408 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2410 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2413 #ifndef DISABLE_REFLECTION_EMIT
2415 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2417 MONO_REQ_GC_NEUTRAL_MODE;
2419 MonoDynamicTable *table;
2421 guint32 token, pclass;
2423 switch (parent & MONO_TYPEDEFORREF_MASK) {
2424 case MONO_TYPEDEFORREF_TYPEREF:
2425 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2427 case MONO_TYPEDEFORREF_TYPESPEC:
2428 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2430 case MONO_TYPEDEFORREF_TYPEDEF:
2431 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2434 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2437 /* extract the index */
2438 parent >>= MONO_TYPEDEFORREF_BITS;
2440 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2442 if (assembly->save) {
2443 alloc_table (table, table->rows + 1);
2444 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2445 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2446 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2447 values [MONO_MEMBERREF_SIGNATURE] = sig;
2450 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2457 * Insert a memberef row into the metadata: the token that point to the memberref
2458 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2459 * mono_image_get_fieldref_token()).
2460 * The sig param is an index to an already built signature.
2463 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2465 MONO_REQ_GC_NEUTRAL_MODE;
2467 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2468 return mono_image_add_memberef_row (assembly, parent, name, sig);
2473 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2475 MONO_REQ_GC_NEUTRAL_MODE;
2478 MonoMethodSignature *sig;
2480 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2482 if (create_typespec) {
2483 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2488 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2489 if (token && !create_typespec)
2492 g_assert (!method->is_inflated);
2495 * A methodref signature can't contain an unmanaged calling convention.
2497 sig = mono_metadata_signature_dup (mono_method_signature (method));
2498 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2499 sig->call_convention = MONO_CALL_DEFAULT;
2500 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2501 method->name, method_encode_signature (assembly, sig));
2503 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2506 if (create_typespec) {
2507 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2508 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2509 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2511 if (assembly->save) {
2514 alloc_table (table, table->rows + 1);
2515 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2516 values [MONO_METHODSPEC_METHOD] = token;
2517 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2520 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2522 /*methodspec and memberef tokens are diferent, */
2523 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2530 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2532 guint32 token, parent, sig;
2533 ReflectionMethodBuilder rmb;
2534 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2536 mono_error_init (error);
2537 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2541 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2545 * A methodref signature can't contain an unmanaged calling convention.
2546 * Since some flags are encoded as part of call_conv, we need to check against it.
2548 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2549 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2551 sig = method_builder_encode_signature (assembly, &rmb, error);
2552 return_val_if_nok (error, 0);
2554 if (tb->generic_params) {
2555 parent = create_generic_typespec (assembly, tb, error);
2556 return_val_if_nok (error, 0);
2558 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2559 return_val_if_nok (error, 0);
2561 parent = mono_image_typedef_or_ref (assembly, t);
2564 char *name = mono_string_to_utf8_checked (method->name, error);
2565 return_val_if_nok (error, 0);
2567 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2570 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2576 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2577 const gchar *name, guint32 sig)
2579 MonoDynamicTable *table;
2583 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2585 if (assembly->save) {
2586 alloc_table (table, table->rows + 1);
2587 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2588 values [MONO_MEMBERREF_CLASS] = original;
2589 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2590 values [MONO_MEMBERREF_SIGNATURE] = sig;
2593 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2600 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2604 guint32 nparams = mono_array_length (mb->generic_params);
2607 if (!assembly->save)
2610 sigbuffer_init (&buf, 32);
2612 sigbuffer_add_value (&buf, 0xa);
2613 sigbuffer_add_value (&buf, nparams);
2615 for (i = 0; i < nparams; i++) {
2616 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2617 sigbuffer_add_value (&buf, i);
2620 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2621 sigbuffer_free (&buf);
2626 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
2628 MonoDynamicTable *table;
2630 guint32 token, mtoken = 0;
2632 mono_error_init (error);
2633 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2637 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2639 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2640 if (!mono_error_ok (error))
2643 switch (mono_metadata_token_table (mtoken)) {
2644 case MONO_TABLE_MEMBERREF:
2645 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2647 case MONO_TABLE_METHOD:
2648 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2651 g_assert_not_reached ();
2654 if (assembly->save) {
2655 alloc_table (table, table->rows + 1);
2656 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2657 values [MONO_METHODSPEC_METHOD] = mtoken;
2658 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2661 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2664 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2669 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
2673 mono_error_init (error);
2675 if (mb->generic_params && create_methodspec)
2676 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
2678 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2682 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2683 if (!mono_error_ok (error))
2685 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2690 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
2692 guint32 token, parent, sig;
2693 ReflectionMethodBuilder rmb;
2695 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2697 mono_error_init (error);
2699 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2703 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
2706 if (tb->generic_params) {
2707 parent = create_generic_typespec (assembly, tb, error);
2708 return_val_if_nok (error, 0);
2710 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
2711 return_val_if_nok (error, 0);
2712 parent = mono_image_typedef_or_ref (assembly, type);
2715 name = mono_string_to_utf8_checked (rmb.name, error);
2716 return_val_if_nok (error, 0);
2717 sig = method_builder_encode_signature (assembly, &rmb, error);
2718 return_val_if_nok (error, 0);
2720 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2723 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2729 is_field_on_inst (MonoClassField *field)
2731 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2735 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2738 get_field_on_inst_generic_type (MonoClassField *field)
2740 MonoClass *klass, *gtd;
2741 MonoDynamicGenericClass *dgclass;
2744 g_assert (is_field_on_inst (field));
2746 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2748 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2749 field_index = field - dgclass->fields;
2750 return dgclass->field_generic_types [field_index];
2753 klass = field->parent;
2754 gtd = klass->generic_class->container_class;
2756 if (field >= klass->fields && field - klass->fields < klass->field.count) {
2757 field_index = field - klass->fields;
2758 return gtd->fields [field_index].type;
2761 g_assert_not_reached ();
2765 #ifndef DISABLE_REFLECTION_EMIT
2767 mono_is_sr_field_on_inst (MonoClassField *field)
2769 return is_field_on_inst (field);
2773 mono_is_sr_field_on_inst (MonoClassField *field)
2777 #endif /*DISABLE_REFLECTION_EMIT*/
2779 #ifndef DISABLE_REFLECTION_EMIT
2781 mono_reflection_get_field_on_inst_generic_type (MonoClassField *field)
2783 return get_field_on_inst_generic_type (field);
2787 mono_reflection_get_field_on_inst_generic_type (MonoClassField *field)
2789 g_assert_not_reached ();
2792 #endif /* DISABLE_REFLECTION_EMIT */
2794 #ifndef DISABLE_REFLECTION_EMIT
2796 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2802 g_assert (field->parent);
2804 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2808 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2809 int index = field - field->parent->fields;
2810 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2812 if (is_field_on_inst (field))
2813 type = get_field_on_inst_generic_type (field);
2815 type = mono_field_get_type (field);
2817 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2818 mono_field_get_name (field),
2819 fieldref_encode_signature (assembly, field->parent->image, type));
2820 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2825 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
2829 MonoGenericClass *gclass;
2833 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2836 if (is_sre_field_builder (mono_object_class (f->fb))) {
2837 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2838 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
2839 return_val_if_nok (error, 0);
2840 klass = mono_class_from_mono_type (type);
2841 gclass = type->data.generic_class;
2842 g_assert (gclass->is_dynamic);
2844 guint32 sig_token = field_encode_signature (assembly, fb, error);
2845 return_val_if_nok (error, 0);
2846 name = mono_string_to_utf8_checked (fb->name, error);
2847 return_val_if_nok (error, 0);
2848 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
2850 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2852 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2854 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
2855 return_val_if_nok (error, 0);
2856 klass = mono_class_from_mono_type (type);
2858 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2859 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2861 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2862 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2865 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2870 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
2874 MonoGenericClass *gclass;
2877 mono_error_init (error);
2879 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2881 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2885 if (mono_is_sre_ctor_builder (mono_object_class (c->cb))) {
2886 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2887 ReflectionMethodBuilder rmb;
2890 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
2891 return_val_if_nok (error, 0);
2892 klass = mono_class_from_mono_type (type);
2894 gclass = type->data.generic_class;
2895 g_assert (gclass->is_dynamic);
2897 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
2900 sig = method_builder_encode_signature (assembly, &rmb, error);
2901 return_val_if_nok (error, 0);
2903 name = mono_string_to_utf8_checked (rmb.name, error);
2904 return_val_if_nok (error, 0);
2906 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2908 } else if (mono_is_sr_mono_cmethod (mono_object_class (c->cb))) {
2909 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2911 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
2912 return_val_if_nok (error, 0);
2913 klass = mono_class_from_mono_type (type);
2915 sig = method_encode_signature (assembly, mono_method_signature (mm));
2916 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2918 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2919 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2923 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2928 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
2931 MonoGenericContext tmp_context;
2932 MonoType **type_argv;
2933 MonoGenericInst *ginst;
2934 MonoMethod *method, *inflated;
2937 mono_error_init (error);
2939 init_type_builder_generics ((MonoObject*)m->inst, error);
2940 return_val_if_nok (error, NULL);
2942 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
2943 return_val_if_nok (error, NULL);
2945 klass = method->klass;
2947 if (m->method_args == NULL)
2950 if (method->is_inflated)
2951 method = ((MonoMethodInflated *) method)->declaring;
2953 count = mono_array_length (m->method_args);
2955 type_argv = g_new0 (MonoType *, count);
2956 for (i = 0; i < count; i++) {
2957 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
2958 type_argv [i] = mono_reflection_type_get_handle (garg, error);
2959 return_val_if_nok (error, NULL);
2961 ginst = mono_metadata_get_generic_inst (count, type_argv);
2964 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2965 tmp_context.method_inst = ginst;
2967 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
2968 mono_error_assert_ok (error);
2973 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
2975 guint32 sig, token = 0;
2979 mono_error_init (error);
2981 if (m->method_args) {
2982 MonoMethod *inflated;
2984 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
2985 return_val_if_nok (error, 0);
2987 if (create_methodspec)
2988 token = mono_image_get_methodspec_token (assembly, inflated);
2990 token = mono_image_get_inflated_method_token (assembly, inflated);
2994 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2998 if (is_sre_method_builder (mono_object_class (m->mb))) {
2999 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3000 MonoGenericClass *gclass;
3001 ReflectionMethodBuilder rmb;
3004 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3005 return_val_if_nok (error, 0);
3006 klass = mono_class_from_mono_type (type);
3007 gclass = type->data.generic_class;
3008 g_assert (gclass->is_dynamic);
3010 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3013 sig = method_builder_encode_signature (assembly, &rmb, error);
3014 return_val_if_nok (error, 0);
3016 name = mono_string_to_utf8_checked (rmb.name, error);
3017 return_val_if_nok (error, 0);
3019 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3021 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3022 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3024 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3025 return_val_if_nok (error, 0);
3026 klass = mono_class_from_mono_type (type);
3028 sig = method_encode_signature (assembly, mono_method_signature (mm));
3029 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3031 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3032 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3035 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3040 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3044 guint32 nparams = context->method_inst->type_argc;
3047 if (!assembly->save)
3050 sigbuffer_init (&buf, 32);
3052 * FIXME: vararg, explicit_this, differenc call_conv values...
3054 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3055 sigbuffer_add_value (&buf, nparams);
3057 for (i = 0; i < nparams; i++)
3058 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3060 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3061 sigbuffer_free (&buf);
3066 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3068 MonoDynamicTable *table;
3070 guint32 token, mtoken = 0, sig;
3071 MonoMethodInflated *imethod;
3072 MonoMethod *declaring;
3074 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3076 g_assert (method->is_inflated);
3077 imethod = (MonoMethodInflated *) method;
3078 declaring = imethod->declaring;
3080 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3081 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3083 if (!mono_method_signature (declaring)->generic_param_count)
3086 switch (mono_metadata_token_table (mtoken)) {
3087 case MONO_TABLE_MEMBERREF:
3088 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3090 case MONO_TABLE_METHOD:
3091 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3094 g_assert_not_reached ();
3097 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3099 if (assembly->save) {
3100 alloc_table (table, table->rows + 1);
3101 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3102 values [MONO_METHODSPEC_METHOD] = mtoken;
3103 values [MONO_METHODSPEC_SIGNATURE] = sig;
3106 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3113 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3115 MonoMethodInflated *imethod;
3118 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3122 g_assert (method->is_inflated);
3123 imethod = (MonoMethodInflated *) method;
3125 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3126 token = method_encode_methodspec (assembly, method);
3128 guint32 sig = method_encode_signature (
3129 assembly, mono_method_signature (imethod->declaring));
3130 token = mono_image_get_memberref_token (
3131 assembly, &method->klass->byval_arg, method->name, sig);
3134 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3139 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3141 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3144 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3145 token = mono_image_get_memberref_token (
3146 assembly, &m->klass->byval_arg, m->name, sig);
3152 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3154 MonoDynamicTable *table;
3163 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3164 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3165 * Because of this, we must not insert it into the `typeref' hash table.
3167 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3168 return_val_if_nok (error, 0);
3169 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3173 sigbuffer_init (&buf, 32);
3175 g_assert (tb->generic_params);
3176 klass = mono_class_from_mono_type (type);
3178 if (tb->generic_container) {
3179 if (!mono_reflection_create_generic_class (tb, error))
3183 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3184 g_assert (klass->generic_container);
3185 sigbuffer_add_value (&buf, klass->byval_arg.type);
3186 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3188 count = mono_array_length (tb->generic_params);
3189 sigbuffer_add_value (&buf, count);
3190 for (i = 0; i < count; i++) {
3191 MonoReflectionGenericParam *gparam;
3193 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3194 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3198 encode_type (assembly, gparam_type, &buf);
3201 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3203 if (assembly->save) {
3204 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3205 alloc_table (table, table->rows + 1);
3206 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3207 values [MONO_TYPESPEC_SIGNATURE] = token;
3209 sigbuffer_free (&buf);
3211 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3212 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3216 sigbuffer_free (&buf);
3221 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3224 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3226 int i, count, len, pos;
3229 mono_error_init (error);
3233 count += mono_array_length (modreq);
3235 count += mono_array_length (modopt);
3238 return mono_metadata_type_dup (NULL, type);
3240 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3241 t = (MonoType *)g_malloc (len);
3242 memcpy (t, type, MONO_SIZEOF_TYPE);
3244 t->num_mods = count;
3247 for (i = 0; i < mono_array_length (modreq); ++i) {
3248 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3251 t->modifiers [pos].required = 1;
3252 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3257 for (i = 0; i < mono_array_length (modopt); ++i) {
3258 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3261 t->modifiers [pos].required = 0;
3262 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3274 init_type_builder_generics (MonoObject *type, MonoError *error)
3276 MonoReflectionTypeBuilder *tb;
3278 mono_error_init (error);
3280 if (!is_sre_type_builder(mono_object_class (type)))
3282 tb = (MonoReflectionTypeBuilder *)type;
3284 if (tb && tb->generic_container)
3285 mono_reflection_create_generic_class (tb, error);
3289 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3291 MonoDynamicTable *table;
3292 MonoType *custom = NULL, *type;
3294 guint32 token, pclass, parent, sig;
3297 mono_error_init (error);
3299 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3303 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3304 return_val_if_nok (error, 0);
3305 /* FIXME: is this call necessary? */
3306 mono_class_from_mono_type (typeb);
3308 /*FIXME this is one more layer of ugliness due how types are created.*/
3309 init_type_builder_generics (fb->type, error);
3310 return_val_if_nok (error, 0);
3312 /* fb->type does not include the custom modifiers */
3313 /* FIXME: We should do this in one place when a fieldbuilder is created */
3314 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3315 return_val_if_nok (error, 0);
3317 if (fb->modreq || fb->modopt) {
3318 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3319 return_val_if_nok (error, 0);
3322 sig = fieldref_encode_signature (assembly, NULL, type);
3325 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3326 return_val_if_nok (error, 0);
3327 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3329 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3330 parent >>= MONO_TYPEDEFORREF_BITS;
3332 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3334 name = mono_string_to_utf8_checked (fb->name, error);
3335 return_val_if_nok (error, 0);
3337 if (assembly->save) {
3338 alloc_table (table, table->rows + 1);
3339 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3340 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3341 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3342 values [MONO_MEMBERREF_SIGNATURE] = sig;
3345 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3347 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3353 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3359 mono_error_init (error);
3361 if (!assembly->save)
3364 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3365 g_assert (helper->type == 2);
3367 if (helper->arguments)
3368 nargs = mono_array_length (helper->arguments);
3372 sigbuffer_init (&buf, 32);
3374 /* Encode calling convention */
3375 /* Change Any to Standard */
3376 if ((helper->call_conv & 0x03) == 0x03)
3377 helper->call_conv = 0x01;
3378 /* explicit_this implies has_this */
3379 if (helper->call_conv & 0x40)
3380 helper->call_conv &= 0x20;
3382 if (helper->call_conv == 0) { /* Unmanaged */
3383 idx = helper->unmanaged_call_conv - 1;
3386 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3387 if (helper->call_conv & 0x02) /* varargs */
3391 sigbuffer_add_byte (&buf, idx);
3392 sigbuffer_add_value (&buf, nargs);
3393 encode_reflection_type (assembly, helper->return_type, &buf, error);
3396 for (i = 0; i < nargs; ++i) {
3397 MonoArray *modreqs = NULL;
3398 MonoArray *modopts = NULL;
3399 MonoReflectionType *pt;
3401 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3402 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3403 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3404 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3406 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3409 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3410 encode_reflection_type (assembly, pt, &buf, error);
3414 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3415 sigbuffer_free (&buf);
3419 sigbuffer_free (&buf);
3424 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3427 MonoDynamicTable *table;
3430 mono_error_init (error);
3432 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3433 idx = table->next_idx ++;
3435 alloc_table (table, table->rows);
3436 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3438 values [MONO_STAND_ALONE_SIGNATURE] =
3439 mono_reflection_encode_sighelper (assembly, helper, error);
3440 return_val_if_nok (error, 0);
3446 reflection_cc_to_file (int call_conv) {
3447 switch (call_conv & 0x3) {
3449 case 1: return MONO_CALL_DEFAULT;
3450 case 2: return MONO_CALL_VARARG;
3452 g_assert_not_reached ();
3456 #endif /* !DISABLE_REFLECTION_EMIT */
3458 struct _ArrayMethod {
3460 MonoMethodSignature *sig;
3466 mono_sre_array_method_free (ArrayMethod *am)
3473 #ifndef DISABLE_REFLECTION_EMIT
3475 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3480 MonoMethodSignature *sig;
3481 ArrayMethod *am = NULL;
3484 mono_error_init (error);
3486 nparams = mono_array_length (m->parameters);
3487 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3489 sig->sentinelpos = -1;
3490 sig->call_convention = reflection_cc_to_file (m->call_conv);
3491 sig->param_count = nparams;
3493 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3497 sig->ret = &mono_defaults.void_class->byval_arg;
3499 mtype = mono_reflection_type_get_handle (m->parent, error);
3503 for (i = 0; i < nparams; ++i) {
3504 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3509 name = mono_string_to_utf8_checked (m->name, error);
3512 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3513 am = (ArrayMethod *)tmp->data;
3514 if (strcmp (name, am->name) == 0 &&
3515 mono_metadata_type_equal (am->parent, mtype) &&
3516 mono_metadata_signature_equal (am->sig, sig)) {
3519 m->table_idx = am->token & 0xffffff;
3523 am = g_new0 (ArrayMethod, 1);
3527 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3528 method_encode_signature (assembly, sig));
3529 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3530 m->table_idx = am->token & 0xffffff;
3541 * Insert into the metadata tables all the info about the TypeBuilder tb.
3542 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3545 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3547 MonoDynamicTable *table;
3549 int i, is_object = 0, is_system = 0;
3552 mono_error_init (error);
3554 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3555 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3556 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3557 n = mono_string_to_utf8_checked (tb->name, error);
3558 return_val_if_nok (error, FALSE);
3559 if (strcmp (n, "Object") == 0)
3561 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3563 n = mono_string_to_utf8_checked (tb->nspace, error);
3564 return_val_if_nok (error, FALSE);
3565 if (strcmp (n, "System") == 0)
3567 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3569 if (tb->parent && !(is_system && is_object) &&
3570 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3571 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3572 return_val_if_nok (error, FALSE);
3573 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3575 values [MONO_TYPEDEF_EXTENDS] = 0;
3577 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3578 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3581 * if we have explicitlayout or sequentiallayouts, output data in the
3582 * ClassLayout table.
3584 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3585 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3586 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3588 alloc_table (table, table->rows);
3589 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3590 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3591 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3592 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3595 /* handle interfaces */
3596 if (tb->interfaces) {
3597 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3599 table->rows += mono_array_length (tb->interfaces);
3600 alloc_table (table, table->rows);
3601 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3602 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3603 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3604 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3605 return_val_if_nok (error, FALSE);
3606 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3607 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3608 values += MONO_INTERFACEIMPL_SIZE;
3614 table = &assembly->tables [MONO_TABLE_FIELD];
3615 table->rows += tb->num_fields;
3616 alloc_table (table, table->rows);
3617 for (i = 0; i < tb->num_fields; ++i) {
3618 mono_image_get_field_info (
3619 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3620 return_val_if_nok (error, FALSE);
3624 /* handle constructors */
3626 table = &assembly->tables [MONO_TABLE_METHOD];
3627 table->rows += mono_array_length (tb->ctors);
3628 alloc_table (table, table->rows);
3629 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3630 if (!mono_image_get_ctor_info (domain,
3631 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3637 /* handle methods */
3639 table = &assembly->tables [MONO_TABLE_METHOD];
3640 table->rows += tb->num_methods;
3641 alloc_table (table, table->rows);
3642 for (i = 0; i < tb->num_methods; ++i) {
3643 if (!mono_image_get_method_info (
3644 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3649 /* Do the same with properties etc.. */
3650 if (tb->events && mono_array_length (tb->events)) {
3651 table = &assembly->tables [MONO_TABLE_EVENT];
3652 table->rows += mono_array_length (tb->events);
3653 alloc_table (table, table->rows);
3654 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3656 alloc_table (table, table->rows);
3657 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3658 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3659 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3660 for (i = 0; i < mono_array_length (tb->events); ++i) {
3661 mono_image_get_event_info (
3662 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
3663 return_val_if_nok (error, FALSE);
3666 if (tb->properties && mono_array_length (tb->properties)) {
3667 table = &assembly->tables [MONO_TABLE_PROPERTY];
3668 table->rows += mono_array_length (tb->properties);
3669 alloc_table (table, table->rows);
3670 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3672 alloc_table (table, table->rows);
3673 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3674 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3675 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3676 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3677 mono_image_get_property_info (
3678 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
3679 return_val_if_nok (error, FALSE);
3683 /* handle generic parameters */
3684 if (tb->generic_params) {
3685 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3686 table->rows += mono_array_length (tb->generic_params);
3687 alloc_table (table, table->rows);
3688 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3689 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3691 mono_image_get_generic_param_info (
3692 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3696 mono_image_add_decl_security (assembly,
3697 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3700 MonoDynamicTable *ntable;
3702 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3703 ntable->rows += mono_array_length (tb->subtypes);
3704 alloc_table (ntable, ntable->rows);
3705 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3707 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3708 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3710 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3711 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3712 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3713 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3714 mono_string_to_utf8 (tb->name), tb->table_idx,
3715 ntable->next_idx, ntable->rows);*/
3716 values += MONO_NESTED_CLASS_SIZE;
3725 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3729 mono_ptr_array_append (*types, type);
3731 if (!type->subtypes)
3734 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3735 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3736 collect_types (types, subtype);
3741 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3743 if ((*type1)->table_idx < (*type2)->table_idx)
3746 if ((*type1)->table_idx > (*type2)->table_idx)
3753 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
3756 mono_error_init (error);
3759 for (i = 0; i < mono_array_length (pinfo); ++i) {
3760 MonoReflectionParamBuilder *pb;
3761 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3764 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
3772 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
3775 mono_error_init (error);
3777 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
3780 for (i = 0; i < tb->num_fields; ++i) {
3781 MonoReflectionFieldBuilder* fb;
3782 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3783 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3788 for (i = 0; i < mono_array_length (tb->events); ++i) {
3789 MonoReflectionEventBuilder* eb;
3790 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3791 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
3795 if (tb->properties) {
3796 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3797 MonoReflectionPropertyBuilder* pb;
3798 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3799 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
3804 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3805 MonoReflectionCtorBuilder* cb;
3806 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3807 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
3808 !params_add_cattrs (assembly, cb->pinfo, error))
3814 for (i = 0; i < tb->num_methods; ++i) {
3815 MonoReflectionMethodBuilder* mb;
3816 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3817 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3818 !params_add_cattrs (assembly, mb->pinfo, error))
3824 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3825 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
3834 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
3838 mono_error_init (error);
3840 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
3843 if (moduleb->global_methods) {
3844 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3845 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3846 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3847 !params_add_cattrs (assembly, mb->pinfo, error))
3852 if (moduleb->global_fields) {
3853 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3854 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3855 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3860 if (moduleb->types) {
3861 for (i = 0; i < moduleb->num_types; ++i) {
3862 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
3871 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly, MonoError *error)
3873 MonoDynamicTable *table;
3877 char *b = blob_size;
3880 mono_error_init (error);
3882 table = &assembly->tables [MONO_TABLE_FILE];
3884 alloc_table (table, table->rows);
3885 values = table->values + table->next_idx * MONO_FILE_SIZE;
3886 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3887 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3888 if (image_is_dynamic (module->image)) {
3889 /* This depends on the fact that the main module is emitted last */
3890 dir = mono_string_to_utf8_checked (((MonoReflectionModuleBuilder*)module)->assemblyb->dir, error);
3891 return_val_if_nok (error, FALSE);
3892 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3895 path = g_strdup (module->image->name);
3897 mono_sha1_get_digest_from_file (path, hash);
3900 mono_metadata_encode_value (20, b, &b);
3901 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3902 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3908 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
3910 MonoDynamicTable *table;
3913 mono_error_init (error);
3915 table = &assembly->tables [MONO_TABLE_MODULE];
3916 mb->table_idx = table->next_idx ++;
3917 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name, error);
3918 return_if_nok (error);
3919 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3922 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3923 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3924 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3925 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3929 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3930 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3932 MonoDynamicTable *table;
3936 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3937 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3940 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3942 alloc_table (table, table->rows);
3943 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3945 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3946 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3947 if (klass->nested_in)
3948 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3950 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3951 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3952 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3954 res = table->next_idx;
3958 /* Emit nested types */
3959 if (klass->ext && klass->ext->nested_classes) {
3962 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3963 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
3970 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3971 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
3977 mono_error_init (error);
3979 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3980 return_if_nok (error);
3982 klass = mono_class_from_mono_type (t);
3984 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3986 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3987 parent_index, assembly);
3991 * We need to do this ourselves since klass->nested_classes is not set up.
3994 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3995 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
3996 return_if_nok (error);
4002 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4003 guint32 module_index, MonoDynamicImage *assembly)
4005 MonoImage *image = module->image;
4009 t = &image->tables [MONO_TABLE_TYPEDEF];
4011 for (i = 0; i < t->rows; ++i) {
4013 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4014 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4016 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4017 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4022 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4024 MonoDynamicTable *table;
4026 guint32 scope, scope_idx, impl, current_idx;
4027 gboolean forwarder = TRUE;
4028 gpointer iter = NULL;
4031 if (klass->nested_in) {
4032 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4035 scope = resolution_scope_from_image (assembly, klass->image);
4036 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4037 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4038 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4041 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4044 alloc_table (table, table->rows);
4045 current_idx = table->next_idx;
4046 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4048 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4049 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4050 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4051 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4052 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4056 while ((nested = mono_class_get_nested_types (klass, &iter)))
4057 add_exported_type (assemblyb, assembly, nested, current_idx);
4061 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4067 if (!assemblyb->type_forwarders)
4070 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4071 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4076 type = mono_reflection_type_get_handle (t, &error);
4077 mono_error_assert_ok (&error);
4080 klass = mono_class_from_mono_type (type);
4082 add_exported_type (assemblyb, assembly, klass, 0);
4086 #define align_pointer(base,p)\
4088 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4090 (p) += 4 - (__diff & 3);\
4094 compare_constants (const void *a, const void *b)
4096 const guint32 *a_values = (const guint32 *)a;
4097 const guint32 *b_values = (const guint32 *)b;
4098 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4102 compare_semantics (const void *a, const void *b)
4104 const guint32 *a_values = (const guint32 *)a;
4105 const guint32 *b_values = (const guint32 *)b;
4106 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4109 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4113 compare_custom_attrs (const void *a, const void *b)
4115 const guint32 *a_values = (const guint32 *)a;
4116 const guint32 *b_values = (const guint32 *)b;
4118 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4122 compare_field_marshal (const void *a, const void *b)
4124 const guint32 *a_values = (const guint32 *)a;
4125 const guint32 *b_values = (const guint32 *)b;
4127 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4131 compare_nested (const void *a, const void *b)
4133 const guint32 *a_values = (const guint32 *)a;
4134 const guint32 *b_values = (const guint32 *)b;
4136 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4140 compare_genericparam (const void *a, const void *b)
4143 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4144 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4146 if ((*b_entry)->owner == (*a_entry)->owner) {
4147 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4148 mono_error_assert_ok (&error);
4149 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4150 mono_error_assert_ok (&error);
4152 mono_type_get_generic_param_num (a_type) -
4153 mono_type_get_generic_param_num (b_type);
4155 return (*a_entry)->owner - (*b_entry)->owner;
4159 compare_declsecurity_attrs (const void *a, const void *b)
4161 const guint32 *a_values = (const guint32 *)a;
4162 const guint32 *b_values = (const guint32 *)b;
4164 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4168 compare_interface_impl (const void *a, const void *b)
4170 const guint32 *a_values = (const guint32 *)a;
4171 const guint32 *b_values = (const guint32 *)b;
4173 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4177 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4182 MonoDynamicStream *stream;
4186 * build_compressed_metadata() fills in the blob of data that represents the
4187 * raw metadata as it will be saved in the PE file. The five streams are output
4188 * and the metadata tables are comnpressed from the guint32 array representation,
4189 * to the compressed on-disk format.
4192 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4194 MonoDynamicTable *table;
4196 guint64 valid_mask = 0;
4197 guint64 sorted_mask;
4198 guint32 heapt_size = 0;
4199 guint32 meta_size = 256; /* allow for header and other stuff */
4200 guint32 table_offset;
4201 guint32 ntables = 0;
4207 struct StreamDesc stream_desc [5];
4209 mono_error_init (error);
4211 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4212 for (i = 0; i < assembly->gen_params->len; i++) {
4213 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4214 if (!write_generic_param_entry (assembly, entry, error))
4218 stream_desc [0].name = "#~";
4219 stream_desc [0].stream = &assembly->tstream;
4220 stream_desc [1].name = "#Strings";
4221 stream_desc [1].stream = &assembly->sheap;
4222 stream_desc [2].name = "#US";
4223 stream_desc [2].stream = &assembly->us;
4224 stream_desc [3].name = "#Blob";
4225 stream_desc [3].stream = &assembly->blob;
4226 stream_desc [4].name = "#GUID";
4227 stream_desc [4].stream = &assembly->guid;
4229 /* tables that are sorted */
4230 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4231 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4232 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4233 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4234 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4235 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4236 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4238 /* Compute table sizes */
4239 /* the MonoImage has already been created in mono_image_basic_init() */
4240 meta = &assembly->image;
4242 /* sizes should be multiple of 4 */
4243 mono_dynstream_data_align (&assembly->blob);
4244 mono_dynstream_data_align (&assembly->guid);
4245 mono_dynstream_data_align (&assembly->sheap);
4246 mono_dynstream_data_align (&assembly->us);
4248 /* Setup the info used by compute_sizes () */
4249 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4250 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4251 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4253 meta_size += assembly->blob.index;
4254 meta_size += assembly->guid.index;
4255 meta_size += assembly->sheap.index;
4256 meta_size += assembly->us.index;
4258 for (i=0; i < MONO_TABLE_NUM; ++i)
4259 meta->tables [i].rows = assembly->tables [i].rows;
4261 for (i = 0; i < MONO_TABLE_NUM; i++){
4262 if (meta->tables [i].rows == 0)
4264 valid_mask |= (guint64)1 << i;
4266 meta->tables [i].row_size = mono_metadata_compute_size (
4267 meta, i, &meta->tables [i].size_bitfield);
4268 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4270 heapt_size += 24; /* #~ header size */
4271 heapt_size += ntables * 4;
4272 /* make multiple of 4 */
4275 meta_size += heapt_size;
4276 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4277 p = (unsigned char*)meta->raw_metadata;
4278 /* the metadata signature */
4279 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4280 /* version numbers and 4 bytes reserved */
4281 int16val = (guint16*)p;
4282 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4283 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4285 /* version string */
4286 int32val = (guint32*)p;
4287 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4289 memcpy (p, meta->version, strlen (meta->version));
4290 p += GUINT32_FROM_LE (*int32val);
4291 align_pointer (meta->raw_metadata, p);
4292 int16val = (guint16*)p;
4293 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4294 *int16val = GUINT16_TO_LE (5); /* number of streams */
4298 * write the stream info.
4300 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4301 table_offset += 3; table_offset &= ~3;
4303 assembly->tstream.index = heapt_size;
4304 for (i = 0; i < 5; ++i) {
4305 int32val = (guint32*)p;
4306 stream_desc [i].stream->offset = table_offset;
4307 *int32val++ = GUINT32_TO_LE (table_offset);
4308 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4309 table_offset += GUINT32_FROM_LE (*int32val);
4310 table_offset += 3; table_offset &= ~3;
4312 strcpy ((char*)p, stream_desc [i].name);
4313 p += strlen (stream_desc [i].name) + 1;
4314 align_pointer (meta->raw_metadata, p);
4317 * now copy the data, the table stream header and contents goes first.
4319 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4320 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4321 int32val = (guint32*)p;
4322 *int32val = GUINT32_TO_LE (0); /* reserved */
4325 *p++ = 2; /* version */
4328 if (meta->idx_string_wide)
4330 if (meta->idx_guid_wide)
4332 if (meta->idx_blob_wide)
4335 *p++ = 1; /* reserved */
4336 int64val = (guint64*)p;
4337 *int64val++ = GUINT64_TO_LE (valid_mask);
4338 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4340 int32val = (guint32*)p;
4341 for (i = 0; i < MONO_TABLE_NUM; i++){
4342 if (meta->tables [i].rows == 0)
4344 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4346 p = (unsigned char*)int32val;
4348 /* sort the tables that still need sorting */
4349 table = &assembly->tables [MONO_TABLE_CONSTANT];
4351 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4352 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4354 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4355 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4357 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4358 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4360 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4361 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4363 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4364 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4365 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4367 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4368 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4370 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4372 /* compress the tables */
4373 for (i = 0; i < MONO_TABLE_NUM; i++){
4376 guint32 bitfield = meta->tables [i].size_bitfield;
4377 if (!meta->tables [i].rows)
4379 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4380 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4381 meta->tables [i].base = (char*)p;
4382 for (row = 1; row <= meta->tables [i].rows; ++row) {
4383 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4384 for (col = 0; col < assembly->tables [i].columns; ++col) {
4385 switch (mono_metadata_table_size (bitfield, col)) {
4387 *p++ = values [col];
4390 *p++ = values [col] & 0xff;
4391 *p++ = (values [col] >> 8) & 0xff;
4394 *p++ = values [col] & 0xff;
4395 *p++ = (values [col] >> 8) & 0xff;
4396 *p++ = (values [col] >> 16) & 0xff;
4397 *p++ = (values [col] >> 24) & 0xff;
4400 g_assert_not_reached ();
4404 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4407 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4408 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4409 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4410 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4411 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4413 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4419 * Some tables in metadata need to be sorted according to some criteria, but
4420 * when methods and fields are first created with reflection, they may be assigned a token
4421 * that doesn't correspond to the final token they will get assigned after the sorting.
4422 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4423 * with the reflection objects that represent them. Once all the tables are set up, the
4424 * reflection objects will contains the correct table index. fixup_method() will fixup the
4425 * tokens for the method with ILGenerator @ilgen.
4428 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4430 guint32 code_idx = GPOINTER_TO_UINT (value);
4431 MonoReflectionILTokenInfo *iltoken;
4432 MonoReflectionFieldBuilder *field;
4433 MonoReflectionCtorBuilder *ctor;
4434 MonoReflectionMethodBuilder *method;
4435 MonoReflectionTypeBuilder *tb;
4436 MonoReflectionArrayMethod *am;
4438 unsigned char *target;
4440 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4441 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4442 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4443 switch (target [3]) {
4444 case MONO_TABLE_FIELD:
4445 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4446 field = (MonoReflectionFieldBuilder *)iltoken->member;
4447 idx = field->table_idx;
4448 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4449 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4450 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4452 g_assert_not_reached ();
4455 case MONO_TABLE_METHOD:
4456 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4457 method = (MonoReflectionMethodBuilder *)iltoken->member;
4458 idx = method->table_idx;
4459 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4460 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4461 idx = ctor->table_idx;
4462 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4463 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4464 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4465 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4467 g_assert_not_reached ();
4470 case MONO_TABLE_TYPEDEF:
4471 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4472 g_assert_not_reached ();
4473 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4474 idx = tb->table_idx;
4476 case MONO_TABLE_MEMBERREF:
4477 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4478 am = (MonoReflectionArrayMethod*)iltoken->member;
4479 idx = am->table_idx;
4480 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4481 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4482 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4483 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4484 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4485 g_assert (m->klass->generic_class || m->klass->generic_container);
4487 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4489 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4490 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4491 g_assert (is_field_on_inst (f));
4493 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4494 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4496 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4498 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4500 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4503 g_assert_not_reached ();
4506 case MONO_TABLE_METHODSPEC:
4507 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4508 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4509 g_assert (mono_method_signature (m)->generic_param_count);
4511 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4513 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4516 g_assert_not_reached ();
4520 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4522 target [0] = idx & 0xff;
4523 target [1] = (idx >> 8) & 0xff;
4524 target [2] = (idx >> 16) & 0xff;
4531 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4532 * value is not known when the table is emitted.
4535 fixup_cattrs (MonoDynamicImage *assembly)
4537 MonoDynamicTable *table;
4539 guint32 type, i, idx, token;
4542 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4544 for (i = 0; i < table->rows; ++i) {
4545 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4547 type = values [MONO_CUSTOM_ATTR_TYPE];
4548 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4549 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4550 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4551 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4554 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4555 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4556 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4557 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4558 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4559 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4560 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4561 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4568 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation, MonoError *error)
4570 MonoDynamicTable *table;
4573 mono_error_init (error);
4575 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4577 alloc_table (table, table->rows);
4578 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4579 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4580 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4581 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name, error);
4582 return_val_if_nok (error, FALSE);
4583 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4589 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, MonoError *error)
4591 MonoDynamicTable *table;
4595 char *b = blob_size;
4597 guint32 idx, offset;
4599 mono_error_init (error);
4601 if (rsrc->filename) {
4602 name = mono_string_to_utf8_checked (rsrc->filename, error);
4603 return_val_if_nok (error, FALSE);
4604 sname = g_path_get_basename (name);
4606 table = &assembly->tables [MONO_TABLE_FILE];
4608 alloc_table (table, table->rows);
4609 values = table->values + table->next_idx * MONO_FILE_SIZE;
4610 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4611 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4614 mono_sha1_get_digest_from_file (name, hash);
4615 mono_metadata_encode_value (20, b, &b);
4616 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4617 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4619 idx = table->next_idx++;
4621 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4627 data = mono_array_addr (rsrc->data, char, 0);
4628 len = mono_array_length (rsrc->data);
4634 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4635 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4636 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4637 mono_image_add_stream_data (&assembly->resources, data, len);
4641 * The entry should be emitted into the MANIFESTRESOURCE table of
4642 * the main module, but that needs to reference the FILE table
4643 * which isn't emitted yet.
4650 return assembly_add_resource_manifest (mb, assembly, rsrc, idx, error);
4654 set_version_from_string (MonoString *version, guint32 *values, MonoError *error)
4656 gchar *ver, *p, *str;
4659 mono_error_init (error);
4661 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4662 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4663 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4664 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4667 ver = str = mono_string_to_utf8_checked (version, error);
4668 return_val_if_nok (error, FALSE);
4669 for (i = 0; i < 4; ++i) {
4670 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4676 /* handle Revision and Build */
4687 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4691 char *b = blob_size;
4696 len = mono_array_length (pkey);
4697 mono_metadata_encode_value (len, b, &b);
4698 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4699 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4701 assembly->public_key = (guint8 *)g_malloc (len);
4702 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4703 assembly->public_key_len = len;
4705 /* Special case: check for ECMA key (16 bytes) */
4706 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4707 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4708 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4709 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4710 /* minimum key size (in 2.0) is 384 bits */
4711 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4713 /* FIXME - verifier */
4714 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4715 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4717 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4723 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
4725 MonoDynamicTable *table;
4726 MonoDynamicImage *assembly;
4727 MonoReflectionAssemblyBuilder *assemblyb;
4731 guint32 module_index;
4733 mono_error_init (error);
4735 assemblyb = moduleb->assemblyb;
4736 assembly = moduleb->dynamic_image;
4737 domain = mono_object_domain (assemblyb);
4739 /* Emit ASSEMBLY table */
4740 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4741 alloc_table (table, 1);
4742 values = table->values + MONO_ASSEMBLY_SIZE;
4743 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4744 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name, error);
4745 return_val_if_nok (error, FALSE);
4746 if (assemblyb->culture) {
4747 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture, error);
4748 return_val_if_nok (error, FALSE);
4750 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4752 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4753 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4754 if (!set_version_from_string (assemblyb->version, values, error))
4757 /* Emit FILE + EXPORTED_TYPE table */
4759 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4761 MonoReflectionModuleBuilder *file_module =
4762 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4763 if (file_module != moduleb) {
4764 if (!mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly, error))
4767 if (file_module->types) {
4768 for (j = 0; j < file_module->num_types; ++j) {
4769 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4770 mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
4771 return_val_if_nok (error, FALSE);
4776 if (assemblyb->loaded_modules) {
4777 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4778 MonoReflectionModule *file_module =
4779 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4780 if (!mono_image_fill_file_table (domain, file_module, assembly, error))
4783 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4786 if (assemblyb->type_forwarders)
4787 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4789 /* Emit MANIFESTRESOURCE table */
4791 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4793 MonoReflectionModuleBuilder *file_module =
4794 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4795 /* The table for the main module is emitted later */
4796 if (file_module != moduleb) {
4798 if (file_module->resources) {
4799 int len = mono_array_length (file_module->resources);
4800 for (j = 0; j < len; ++j) {
4801 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4802 if (!assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS), error))
4811 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4814 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4815 * for the modulebuilder @moduleb.
4816 * At the end of the process, method and field tokens are fixed up and the
4817 * on-disk compressed metadata representation is created.
4818 * Return TRUE on success, or FALSE on failure and sets @error
4821 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
4823 MonoDynamicTable *table;
4824 MonoDynamicImage *assembly;
4825 MonoReflectionAssemblyBuilder *assemblyb;
4831 mono_error_init (error);
4833 assemblyb = moduleb->assemblyb;
4834 assembly = moduleb->dynamic_image;
4835 domain = mono_object_domain (assemblyb);
4837 if (assembly->text_rva)
4840 assembly->text_rva = START_TEXT_RVA;
4842 if (moduleb->is_main) {
4843 mono_image_emit_manifest (moduleb, error);
4844 return_val_if_nok (error, FALSE);
4847 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4848 table->rows = 1; /* .<Module> */
4850 alloc_table (table, table->rows);
4852 * Set the first entry.
4854 values = table->values + table->columns;
4855 values [MONO_TYPEDEF_FLAGS] = 0;
4856 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4857 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4858 values [MONO_TYPEDEF_EXTENDS] = 0;
4859 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4860 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4863 * handle global methods
4864 * FIXME: test what to do when global methods are defined in multiple modules.
4866 if (moduleb->global_methods) {
4867 table = &assembly->tables [MONO_TABLE_METHOD];
4868 table->rows += mono_array_length (moduleb->global_methods);
4869 alloc_table (table, table->rows);
4870 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4871 if (!mono_image_get_method_info (
4872 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
4876 if (moduleb->global_fields) {
4877 table = &assembly->tables [MONO_TABLE_FIELD];
4878 table->rows += mono_array_length (moduleb->global_fields);
4879 alloc_table (table, table->rows);
4880 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4881 mono_image_get_field_info (
4882 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
4889 table = &assembly->tables [MONO_TABLE_MODULE];
4890 alloc_table (table, 1);
4891 mono_image_fill_module_table (domain, moduleb, assembly, error);
4895 /* Collect all types into a list sorted by their table_idx */
4896 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4899 for (i = 0; i < moduleb->num_types; ++i) {
4900 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4901 collect_types (&types, type);
4904 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
4905 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4906 table->rows += mono_ptr_array_size (types);
4907 alloc_table (table, table->rows);
4910 * Emit type names + namespaces at one place inside the string heap,
4911 * so load_class_names () needs to touch fewer pages.
4913 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4914 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4915 string_heap_insert_mstring (&assembly->sheap, tb->nspace, error);
4919 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4920 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4921 string_heap_insert_mstring (&assembly->sheap, tb->name, error);
4926 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4927 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4928 if (!mono_image_get_type_info (domain, type, assembly, error))
4933 * table->rows is already set above and in mono_image_fill_module_table.
4935 /* add all the custom attributes at the end, once all the indexes are stable */
4936 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
4939 /* CAS assembly permissions */
4940 if (assemblyb->permissions_minimum)
4941 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4942 if (assemblyb->permissions_optional)
4943 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4944 if (assemblyb->permissions_refused)
4945 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4947 if (!module_add_cattrs (assembly, moduleb, error))
4951 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4953 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4954 * the final tokens and don't need another fixup pass. */
4956 if (moduleb->global_methods) {
4957 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4958 MonoReflectionMethodBuilder *mb = mono_array_get (
4959 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4960 if (!mono_image_add_methodimpl (assembly, mb, error))
4965 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4966 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
4967 if (type->methods) {
4968 for (j = 0; j < type->num_methods; ++j) {
4969 MonoReflectionMethodBuilder *mb = mono_array_get (
4970 type->methods, MonoReflectionMethodBuilder*, j);
4972 if (!mono_image_add_methodimpl (assembly, mb, error))
4978 fixup_cattrs (assembly);
4981 mono_ptr_array_destroy (types);
4984 return mono_error_ok (error);
4987 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4990 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
4992 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4995 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4998 #ifndef DISABLE_REFLECTION_EMIT
5001 * mono_image_insert_string:
5002 * @module: module builder object
5005 * Insert @str into the user string stream of @module.
5008 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5010 MonoDynamicImage *assembly;
5015 if (!module->dynamic_image)
5016 mono_image_module_basic_init (module);
5018 assembly = module->dynamic_image;
5020 if (assembly->save) {
5021 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5022 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5023 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5025 char *swapped = g_malloc (2 * mono_string_length (str));
5026 const char *p = (const char*)mono_string_chars (str);
5028 swap_with_size (swapped, p, 2, mono_string_length (str));
5029 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5033 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5035 mono_image_add_stream_data (&assembly->us, "", 1);
5037 idx = assembly->us.index ++;
5040 mono_dynamic_image_register_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5042 return MONO_TOKEN_STRING | idx;
5046 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5050 MonoMethodSignature *sig;
5052 mono_error_init (error);
5054 klass = obj->vtable->klass;
5055 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5056 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5057 MonoMethodSignature *old;
5058 guint32 sig_token, parent;
5061 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5063 nargs = mono_array_length (opt_param_types);
5064 old = mono_method_signature (method);
5065 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5067 sig->hasthis = old->hasthis;
5068 sig->explicit_this = old->explicit_this;
5069 sig->call_convention = old->call_convention;
5070 sig->generic_param_count = old->generic_param_count;
5071 sig->param_count = old->param_count + nargs;
5072 sig->sentinelpos = old->param_count;
5073 sig->ret = old->ret;
5075 for (i = 0; i < old->param_count; i++)
5076 sig->params [i] = old->params [i];
5078 for (i = 0; i < nargs; i++) {
5079 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5080 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5081 if (!is_ok (error)) goto fail;
5084 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5085 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5086 parent >>= MONO_TYPEDEFORREF_BITS;
5088 parent <<= MONO_MEMBERREF_PARENT_BITS;
5089 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5091 sig_token = method_encode_signature (assembly, sig);
5092 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5093 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5094 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5095 ReflectionMethodBuilder rmb;
5096 guint32 parent, sig_token;
5097 int nopt_args, nparams, ngparams, i;
5099 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5102 rmb.opt_types = opt_param_types;
5103 nopt_args = mono_array_length (opt_param_types);
5105 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5106 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5107 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5109 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5110 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5111 sig->call_convention = rmb.call_conv;
5112 sig->generic_param_count = ngparams;
5113 sig->param_count = nparams + nopt_args;
5114 sig->sentinelpos = nparams;
5115 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5116 if (!is_ok (error)) goto fail;
5118 for (i = 0; i < nparams; i++) {
5119 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5120 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5121 if (!is_ok (error)) goto fail;
5124 for (i = 0; i < nopt_args; i++) {
5125 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5126 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5127 if (!is_ok (error)) goto fail;
5130 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5134 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5135 if (!mono_error_ok (error))
5137 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5139 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5140 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5142 char *name = mono_string_to_utf8_checked (rmb.name, error);
5143 if (!is_ok (error)) goto fail;
5144 token = mono_image_get_varargs_method_token (
5145 assembly, parent, name, sig_token);
5148 g_error ("requested method token for %s\n", klass->name);
5151 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5152 mono_dynamic_image_register_token (assembly, token, obj);
5155 g_assert (!mono_error_ok (error));
5160 * mono_image_create_token:
5161 * @assembly: a dynamic assembly
5163 * @register_token: Whenever to register the token in the assembly->tokens hash.
5165 * Get a token to insert in the IL code stream for the given MemberInfo.
5166 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5167 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5171 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5172 gboolean create_open_instance, gboolean register_token,
5178 mono_error_init (error);
5180 klass = obj->vtable->klass;
5182 /* Check for user defined reflection objects */
5183 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5184 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5185 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5189 if (strcmp (klass->name, "MethodBuilder") == 0) {
5190 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5191 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5193 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5194 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5196 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5197 if (!mono_error_ok (error))
5200 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5201 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5202 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5203 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5205 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5206 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5208 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5209 if (!mono_error_ok (error))
5212 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5213 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5214 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5215 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5216 if (tb->generic_params) {
5217 token = mono_image_get_generic_field_token (assembly, fb, error);
5218 return_val_if_nok (error, 0);
5220 if (tb->module->dynamic_image == assembly) {
5221 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5223 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5226 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5227 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5228 if (create_open_instance && tb->generic_params) {
5230 init_type_builder_generics (obj, error);
5231 return_val_if_nok (error, 0);
5232 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5233 return_val_if_nok (error, 0);
5234 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5235 token = mono_metadata_token_from_dor (token);
5236 } else if (tb->module->dynamic_image == assembly) {
5237 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5240 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5241 return_val_if_nok (error, 0);
5242 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5244 } else if (strcmp (klass->name, "RuntimeType") == 0) {
5245 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5246 return_val_if_nok (error, 0);
5247 MonoClass *mc = mono_class_from_mono_type (type);
5248 token = mono_metadata_token_from_dor (
5249 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5250 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5251 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5252 return_val_if_nok (error, 0);
5253 token = mono_metadata_token_from_dor (
5254 mono_image_typedef_or_ref (assembly, type));
5255 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5256 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5257 return_val_if_nok (error, 0);
5258 token = mono_metadata_token_from_dor (
5259 mono_image_typedef_or_ref (assembly, type));
5260 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5261 strcmp (klass->name, "MonoMethod") == 0 ||
5262 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5263 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5264 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5265 if (m->method->is_inflated) {
5266 if (create_open_instance)
5267 token = mono_image_get_methodspec_token (assembly, m->method);
5269 token = mono_image_get_inflated_method_token (assembly, m->method);
5270 } else if ((m->method->klass->image == &assembly->image) &&
5271 !m->method->klass->generic_class) {
5272 static guint32 method_table_idx = 0xffffff;
5273 if (m->method->klass->wastypebuilder) {
5274 /* we use the same token as the one that was assigned
5275 * to the Methodbuilder.
5276 * FIXME: do the equivalent for Fields.
5278 token = m->method->token;
5281 * Each token should have a unique index, but the indexes are
5282 * assigned by managed code, so we don't know about them. An
5283 * easy solution is to count backwards...
5285 method_table_idx --;
5286 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5289 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5291 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5292 } else if (strcmp (klass->name, "MonoField") == 0) {
5293 MonoReflectionField *f = (MonoReflectionField *)obj;
5294 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5295 static guint32 field_table_idx = 0xffffff;
5297 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5299 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5301 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5302 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5303 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5304 token = mono_image_get_array_token (assembly, m, error);
5305 return_val_if_nok (error, 0);
5306 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5307 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5308 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5309 return_val_if_nok (error, 0);
5310 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5311 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5312 return_val_if_nok (error, 0);
5313 token = mono_metadata_token_from_dor (
5314 mono_image_typedef_or_ref (assembly, type));
5315 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5316 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5317 token = mono_image_get_field_on_inst_token (assembly, f, error);
5318 return_val_if_nok (error, 0);
5319 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5320 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5321 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5322 if (!mono_error_ok (error))
5324 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5325 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5326 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5327 if (!mono_error_ok (error))
5329 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5330 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5331 return_val_if_nok (error, 0);
5332 token = mono_metadata_token_from_dor (
5333 mono_image_typedef_or_ref (assembly, type));
5335 g_error ("requested token for %s\n", klass->name);
5339 mono_image_register_token (assembly, token, obj);
5347 #ifndef DISABLE_REFLECTION_EMIT
5350 * mono_image_basic_init:
5351 * @assembly: an assembly builder object
5353 * Create the MonoImage that represents the assembly builder and setup some
5354 * of the helper hash table and the basic metadata streams.
5357 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5360 MonoDynamicAssembly *assembly;
5361 MonoDynamicImage *image;
5362 MonoDomain *domain = mono_object_domain (assemblyb);
5364 if (assemblyb->dynamic_assembly)
5368 /* assembly->assembly.image might be GC allocated */
5369 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5371 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5374 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5376 assembly->assembly.ref_count = 1;
5377 assembly->assembly.dynamic = TRUE;
5378 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5379 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5380 assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
5381 if (mono_error_set_pending_exception (&error))
5383 if (assemblyb->culture) {
5384 assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
5385 if (mono_error_set_pending_exception (&error))
5388 assembly->assembly.aname.culture = g_strdup ("");
5390 if (assemblyb->version) {
5391 char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
5392 if (mono_error_set_pending_exception (&error))
5394 char **version = g_strsplit (vstr, ".", 4);
5395 char **parts = version;
5396 assembly->assembly.aname.major = atoi (*parts++);
5397 assembly->assembly.aname.minor = atoi (*parts++);
5398 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5399 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5401 g_strfreev (version);
5404 assembly->assembly.aname.major = 0;
5405 assembly->assembly.aname.minor = 0;
5406 assembly->assembly.aname.build = 0;
5407 assembly->assembly.aname.revision = 0;
5410 assembly->run = assemblyb->access != 2;
5411 assembly->save = assemblyb->access != 1;
5412 assembly->domain = domain;
5414 char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
5415 if (mono_error_set_pending_exception (&error))
5417 image = mono_dynamic_image_create (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
5418 image->initial_image = TRUE;
5419 assembly->assembly.aname.name = image->image.name;
5420 assembly->assembly.image = &image->image;
5421 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5422 /* -1 to correct for the trailing NULL byte */
5423 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5424 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5426 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5429 mono_domain_assemblies_lock (domain);
5430 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5431 mono_domain_assemblies_unlock (domain);
5433 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5435 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5437 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5440 #endif /* !DISABLE_REFLECTION_EMIT */
5442 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5445 calc_section_size (MonoDynamicImage *assembly)
5449 /* alignment constraints */
5450 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5451 g_assert ((assembly->code.index % 4) == 0);
5452 assembly->meta_size += 3;
5453 assembly->meta_size &= ~3;
5454 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5455 g_assert ((assembly->resources.index % 4) == 0);
5457 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5458 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5461 if (assembly->win32_res) {
5462 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5464 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5465 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5469 assembly->sections [MONO_SECTION_RELOC].size = 12;
5470 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5480 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5484 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5486 ResTreeNode *t1 = (ResTreeNode*)a;
5487 ResTreeNode *t2 = (ResTreeNode*)b;
5489 return t1->id - t2->id;
5493 * resource_tree_create:
5495 * Organize the resources into a resource tree.
5497 static ResTreeNode *
5498 resource_tree_create (MonoArray *win32_resources)
5500 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5504 tree = g_new0 (ResTreeNode, 1);
5506 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5507 MonoReflectionWin32Resource *win32_res =
5508 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5512 /* FIXME: BUG: this stores managed references in unmanaged memory */
5513 lang_node = g_new0 (ResTreeNode, 1);
5514 lang_node->id = win32_res->lang_id;
5515 lang_node->win32_res = win32_res;
5517 /* Create type node if neccesary */
5519 for (l = tree->children; l; l = l->next)
5520 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5521 type_node = (ResTreeNode*)l->data;
5526 type_node = g_new0 (ResTreeNode, 1);
5527 type_node->id = win32_res->res_type;
5530 * The resource types have to be sorted otherwise
5531 * Windows Explorer can't display the version information.
5533 tree->children = g_slist_insert_sorted (tree->children,
5534 type_node, resource_tree_compare_by_id);
5537 /* Create res node if neccesary */
5539 for (l = type_node->children; l; l = l->next)
5540 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5541 res_node = (ResTreeNode*)l->data;
5546 res_node = g_new0 (ResTreeNode, 1);
5547 res_node->id = win32_res->res_id;
5548 type_node->children = g_slist_append (type_node->children, res_node);
5551 res_node->children = g_slist_append (res_node->children, lang_node);
5558 * resource_tree_encode:
5560 * Encode the resource tree into the format used in the PE file.
5563 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5566 MonoPEResourceDir dir;
5567 MonoPEResourceDirEntry dir_entry;
5568 MonoPEResourceDataEntry data_entry;
5570 guint32 res_id_entries;
5573 * For the format of the resource directory, see the article
5574 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5578 memset (&dir, 0, sizeof (dir));
5579 memset (&dir_entry, 0, sizeof (dir_entry));
5580 memset (&data_entry, 0, sizeof (data_entry));
5582 g_assert (sizeof (dir) == 16);
5583 g_assert (sizeof (dir_entry) == 8);
5584 g_assert (sizeof (data_entry) == 16);
5586 node->offset = p - begin;
5588 /* IMAGE_RESOURCE_DIRECTORY */
5589 res_id_entries = g_slist_length (node->children);
5590 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5592 memcpy (p, &dir, sizeof (dir));
5595 /* Reserve space for entries */
5597 p += sizeof (dir_entry) * res_id_entries;
5599 /* Write children */
5600 for (l = node->children; l; l = l->next) {
5601 ResTreeNode *child = (ResTreeNode*)l->data;
5603 if (child->win32_res) {
5606 child->offset = p - begin;
5608 /* IMAGE_RESOURCE_DATA_ENTRY */
5609 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5610 size = mono_array_length (child->win32_res->res_data);
5611 data_entry.rde_size = GUINT32_TO_LE (size);
5613 memcpy (p, &data_entry, sizeof (data_entry));
5614 p += sizeof (data_entry);
5616 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5619 resource_tree_encode (child, begin, p, &p);
5623 /* IMAGE_RESOURCE_ENTRY */
5624 for (l = node->children; l; l = l->next) {
5625 ResTreeNode *child = (ResTreeNode*)l->data;
5627 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5628 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5630 memcpy (entries, &dir_entry, sizeof (dir_entry));
5631 entries += sizeof (dir_entry);
5638 resource_tree_free (ResTreeNode * node)
5641 for (list = node->children; list; list = list->next)
5642 resource_tree_free ((ResTreeNode*)list->data);
5643 g_slist_free(node->children);
5648 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5653 MonoReflectionWin32Resource *win32_res;
5656 if (!assemblyb->win32_resources)
5660 * Resources are stored in a three level tree inside the PE file.
5661 * - level one contains a node for each type of resource
5662 * - level two contains a node for each resource
5663 * - level three contains a node for each instance of a resource for a
5664 * specific language.
5667 tree = resource_tree_create (assemblyb->win32_resources);
5669 /* Estimate the size of the encoded tree */
5671 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5672 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5673 size += mono_array_length (win32_res->res_data);
5675 /* Directory structure */
5676 size += mono_array_length (assemblyb->win32_resources) * 256;
5677 p = buf = (char *)g_malloc (size);
5679 resource_tree_encode (tree, p, p, &p);
5681 g_assert (p - buf <= size);
5683 assembly->win32_res = (char *)g_malloc (p - buf);
5684 assembly->win32_res_size = p - buf;
5685 memcpy (assembly->win32_res, buf, p - buf);
5688 resource_tree_free (tree);
5692 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5694 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5697 p += sizeof (MonoPEResourceDir);
5698 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5699 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5700 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5701 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5702 fixup_resource_directory (res_section, child, rva);
5704 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5705 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5708 p += sizeof (MonoPEResourceDirEntry);
5713 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5716 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5717 g_error ("WriteFile returned %d\n", GetLastError ());
5721 * mono_image_create_pefile:
5722 * @mb: a module builder object
5724 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5725 * assembly->pefile where it can be easily retrieved later in chunks.
5728 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
5730 MonoMSDOSHeader *msdos;
5731 MonoDotNetHeader *header;
5732 MonoSectionTable *section;
5733 MonoCLIHeader *cli_header;
5734 guint32 size, image_size, virtual_base, text_offset;
5735 guint32 header_start, section_start, file_offset, virtual_offset;
5736 MonoDynamicImage *assembly;
5737 MonoReflectionAssemblyBuilder *assemblyb;
5738 MonoDynamicStream pefile_stream = {0};
5739 MonoDynamicStream *pefile = &pefile_stream;
5741 guint32 *rva, value;
5743 static const unsigned char msheader[] = {
5744 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5745 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5746 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5747 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5748 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5749 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5750 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5751 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5754 mono_error_init (error);
5756 assemblyb = mb->assemblyb;
5758 mono_image_basic_init (assemblyb);
5759 assembly = mb->dynamic_image;
5761 assembly->pe_kind = assemblyb->pe_kind;
5762 assembly->machine = assemblyb->machine;
5763 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5764 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5766 if (!mono_image_build_metadata (mb, error))
5770 if (mb->is_main && assemblyb->resources) {
5771 int len = mono_array_length (assemblyb->resources);
5772 for (i = 0; i < len; ++i) {
5773 if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i), error))
5778 if (mb->resources) {
5779 int len = mono_array_length (mb->resources);
5780 for (i = 0; i < len; ++i) {
5781 if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i), error))
5786 if (!build_compressed_metadata (assembly, error))
5790 assembly_add_win32_resources (assembly, assemblyb);
5792 nsections = calc_section_size (assembly);
5794 /* The DOS header and stub */
5795 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5796 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5798 /* the dotnet header */
5799 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5801 /* the section tables */
5802 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5804 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5805 virtual_offset = VIRT_ALIGN;
5808 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5809 if (!assembly->sections [i].size)
5812 file_offset += FILE_ALIGN - 1;
5813 file_offset &= ~(FILE_ALIGN - 1);
5814 virtual_offset += VIRT_ALIGN - 1;
5815 virtual_offset &= ~(VIRT_ALIGN - 1);
5817 assembly->sections [i].offset = file_offset;
5818 assembly->sections [i].rva = virtual_offset;
5820 file_offset += assembly->sections [i].size;
5821 virtual_offset += assembly->sections [i].size;
5822 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5825 file_offset += FILE_ALIGN - 1;
5826 file_offset &= ~(FILE_ALIGN - 1);
5828 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5830 /* back-patch info */
5831 msdos = (MonoMSDOSHeader*)pefile->data;
5832 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5834 header = (MonoDotNetHeader*)(pefile->data + header_start);
5835 header->pesig [0] = 'P';
5836 header->pesig [1] = 'E';
5838 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5839 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5840 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5841 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5842 if (assemblyb->pekind == 1) {
5844 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5847 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5850 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5852 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5853 header->pe.pe_major = 6;
5854 header->pe.pe_minor = 0;
5855 size = assembly->sections [MONO_SECTION_TEXT].size;
5856 size += FILE_ALIGN - 1;
5857 size &= ~(FILE_ALIGN - 1);
5858 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5859 size = assembly->sections [MONO_SECTION_RSRC].size;
5860 size += FILE_ALIGN - 1;
5861 size &= ~(FILE_ALIGN - 1);
5862 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5863 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5864 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5865 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5866 /* pe_rva_entry_point always at the beginning of the text section */
5867 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5869 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5870 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5871 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5872 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5873 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5874 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5875 size = section_start;
5876 size += FILE_ALIGN - 1;
5877 size &= ~(FILE_ALIGN - 1);
5878 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5880 size += VIRT_ALIGN - 1;
5881 size &= ~(VIRT_ALIGN - 1);
5882 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5885 // Translate the PEFileKind value to the value expected by the Windows loader
5891 // PEFileKinds.Dll == 1
5892 // PEFileKinds.ConsoleApplication == 2
5893 // PEFileKinds.WindowApplication == 3
5896 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5897 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5899 if (assemblyb->pekind == 3)
5904 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5906 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5907 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5908 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5909 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5910 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5911 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5913 /* fill data directory entries */
5915 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5916 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5918 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5919 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5921 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5922 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5923 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5924 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5925 /* patch entrypoint name */
5926 if (assemblyb->pekind == 1)
5927 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5929 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5930 /* patch imported function RVA name */
5931 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5932 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5934 /* the import table */
5935 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5936 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5937 /* patch imported dll RVA name and other entries in the dir */
5938 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5939 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5940 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5941 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5942 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5943 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5945 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5946 value = (assembly->text_rva + assembly->imp_names_offset);
5947 *p++ = (value) & 0xff;
5948 *p++ = (value >> 8) & (0xff);
5949 *p++ = (value >> 16) & (0xff);
5950 *p++ = (value >> 24) & (0xff);
5952 /* the CLI header info */
5953 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5954 cli_header->ch_size = GUINT32_FROM_LE (72);
5955 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5956 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5957 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5958 if (assemblyb->entry_point) {
5959 guint32 table_idx = 0;
5960 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5961 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5962 table_idx = methodb->table_idx;
5964 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5966 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5968 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5970 /* The embedded managed resources */
5971 text_offset = assembly->text_rva + assembly->code.index;
5972 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5973 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5974 text_offset += assembly->resources.index;
5975 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5976 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5977 text_offset += assembly->meta_size;
5978 if (assembly->strong_name_size) {
5979 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5980 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5981 text_offset += assembly->strong_name_size;
5984 /* write the section tables and section content */
5985 section = (MonoSectionTable*)(pefile->data + section_start);
5986 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5987 static const char section_names [][7] = {
5988 ".text", ".rsrc", ".reloc"
5990 if (!assembly->sections [i].size)
5992 strcpy (section->st_name, section_names [i]);
5993 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5994 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5995 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5996 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5997 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5998 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5999 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6003 checked_write_file (file, pefile->data, pefile->index);
6005 mono_dynamic_stream_reset (pefile);
6007 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6008 if (!assembly->sections [i].size)
6011 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6012 g_error ("SetFilePointer returned %d\n", GetLastError ());
6015 case MONO_SECTION_TEXT:
6016 /* patch entry point */
6017 p = (guchar*)(assembly->code.data + 2);
6018 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6019 *p++ = (value) & 0xff;
6020 *p++ = (value >> 8) & 0xff;
6021 *p++ = (value >> 16) & 0xff;
6022 *p++ = (value >> 24) & 0xff;
6024 checked_write_file (file, assembly->code.data, assembly->code.index);
6025 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6026 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6027 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6030 g_free (assembly->image.raw_metadata);
6032 case MONO_SECTION_RELOC: {
6036 guint16 type_and_offset;
6040 g_assert (sizeof (reloc) == 12);
6042 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6043 reloc.block_size = GUINT32_FROM_LE (12);
6046 * the entrypoint is always at the start of the text section
6047 * 3 is IMAGE_REL_BASED_HIGHLOW
6048 * 2 is patch_size_rva - text_rva
6050 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6053 checked_write_file (file, &reloc, sizeof (reloc));
6057 case MONO_SECTION_RSRC:
6058 if (assembly->win32_res) {
6060 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6061 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6062 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6066 g_assert_not_reached ();
6070 /* check that the file is properly padded */
6071 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6072 g_error ("SetFilePointer returned %d\n", GetLastError ());
6073 if (! SetEndOfFile (file))
6074 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6076 mono_dynamic_stream_reset (&assembly->code);
6077 mono_dynamic_stream_reset (&assembly->us);
6078 mono_dynamic_stream_reset (&assembly->blob);
6079 mono_dynamic_stream_reset (&assembly->guid);
6080 mono_dynamic_stream_reset (&assembly->sheap);
6082 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6083 g_hash_table_destroy (assembly->blob_cache);
6084 assembly->blob_cache = NULL;
6089 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6092 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6094 g_assert_not_reached ();
6097 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6099 #ifndef DISABLE_REFLECTION_EMIT
6101 MonoReflectionModule *
6102 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6106 MonoImageOpenStatus status;
6107 MonoDynamicAssembly *assembly;
6108 guint32 module_count;
6109 MonoImage **new_modules;
6110 gboolean *new_modules_loaded;
6112 mono_error_init (error);
6114 name = mono_string_to_utf8_checked (fileName, error);
6115 return_val_if_nok (error, NULL);
6117 image = mono_image_open (name, &status);
6119 if (status == MONO_IMAGE_ERROR_ERRNO)
6120 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6122 mono_error_set_bad_image_name (error, name, NULL);
6129 assembly = ab->dynamic_assembly;
6130 image->assembly = (MonoAssembly*)assembly;
6132 module_count = image->assembly->image->module_count;
6133 new_modules = g_new0 (MonoImage *, module_count + 1);
6134 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6136 if (image->assembly->image->modules)
6137 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6138 if (image->assembly->image->modules_loaded)
6139 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6140 new_modules [module_count] = image;
6141 new_modules_loaded [module_count] = TRUE;
6142 mono_image_addref (image);
6144 g_free (image->assembly->image->modules);
6145 image->assembly->image->modules = new_modules;
6146 image->assembly->image->modules_loaded = new_modules_loaded;
6147 image->assembly->image->module_count ++;
6149 mono_assembly_load_references (image, &status);
6151 mono_image_close (image);
6152 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6156 return mono_module_get_object_checked (mono_domain_get (), image, error);
6159 #endif /* DISABLE_REFLECTION_EMIT */
6161 #ifndef DISABLE_REFLECTION_EMIT
6163 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6165 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6169 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6171 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6175 image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
6177 MonoDynamicImage *image = moduleb->dynamic_image;
6178 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6179 mono_error_init (error);
6182 MonoImage **new_modules;
6184 char *name, *fqname;
6186 * FIXME: we already created an image in mono_image_basic_init (), but
6187 * we don't know which module it belongs to, since that is only
6188 * determined at assembly save time.
6190 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6191 name = mono_string_to_utf8_checked (ab->name, error);
6192 return_val_if_nok (error, FALSE);
6193 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
6194 if (!is_ok (error)) {
6198 image = mono_dynamic_image_create (ab->dynamic_assembly, name, fqname);
6200 moduleb->module.image = &image->image;
6201 moduleb->dynamic_image = image;
6202 register_module (mono_object_domain (moduleb), moduleb, image);
6204 /* register the module with the assembly */
6205 ass = ab->dynamic_assembly->assembly.image;
6206 module_count = ass->module_count;
6207 new_modules = g_new0 (MonoImage *, module_count + 1);
6210 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6211 new_modules [module_count] = &image->image;
6212 mono_image_addref (&image->image);
6214 g_free (ass->modules);
6215 ass->modules = new_modules;
6216 ass->module_count ++;
6222 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6225 (void) image_module_basic_init (moduleb, &error);
6226 mono_error_set_pending_exception (&error);
6232 is_corlib_type (MonoClass *klass)
6234 return klass->image == mono_defaults.corlib;
6237 #define check_corlib_type_cached(_class, _namespace, _name) do { \
6238 static MonoClass *cached_class; \
6240 return cached_class == _class; \
6241 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
6242 cached_class = _class; \
6250 #ifndef DISABLE_REFLECTION_EMIT
6252 is_sre_array (MonoClass *klass)
6254 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
6258 is_sre_byref (MonoClass *klass)
6260 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
6264 is_sre_pointer (MonoClass *klass)
6266 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
6270 is_sre_generic_instance (MonoClass *klass)
6272 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
6276 is_sre_type_builder (MonoClass *klass)
6278 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
6282 is_sre_method_builder (MonoClass *klass)
6284 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
6288 mono_is_sre_ctor_builder (MonoClass *klass)
6290 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
6294 is_sre_field_builder (MonoClass *klass)
6296 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
6300 mono_is_sre_method_on_tb_inst (MonoClass *klass)
6302 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
6306 mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
6308 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
6311 static MonoReflectionType*
6312 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
6314 static MonoMethod *method_get_underlying_system_type = NULL;
6315 MonoReflectionType *rt;
6316 MonoMethod *usertype_method;
6318 mono_error_init (error);
6320 if (!method_get_underlying_system_type)
6321 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
6323 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
6325 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
6331 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
6333 mono_error_init (error);
6334 if (!type || type->type)
6337 if (mono_reflection_is_usertype (type)) {
6338 type = mono_reflection_type_get_underlying_system_type (type, error);
6339 return_val_if_nok (error, NULL);
6340 if (mono_reflection_is_usertype (type)) {
6341 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
6351 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
6354 mono_error_init (error);
6361 if (mono_reflection_is_usertype (ref)) {
6362 ref = mono_reflection_type_get_underlying_system_type (ref, error);
6363 if (ref == NULL || mono_reflection_is_usertype (ref) || !is_ok (error))
6369 klass = mono_object_class (ref);
6371 if (is_sre_array (klass)) {
6373 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
6374 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
6375 return_val_if_nok (error, NULL);
6377 if (sre_array->rank == 0) //single dimentional array
6378 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
6380 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
6381 sre_array->type.type = res;
6383 } else if (is_sre_byref (klass)) {
6385 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
6386 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
6387 return_val_if_nok (error, NULL);
6389 res = &mono_class_from_mono_type (base)->this_arg;
6390 sre_byref->type.type = res;
6392 } else if (is_sre_pointer (klass)) {
6394 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
6395 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
6396 return_val_if_nok (error, NULL);
6398 res = &mono_ptr_class_get (base)->byval_arg;
6399 sre_pointer->type.type = res;
6401 } else if (is_sre_generic_instance (klass)) {
6402 MonoType *res, **types;
6403 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
6406 count = mono_array_length (gclass->type_arguments);
6407 types = g_new0 (MonoType*, count);
6408 for (i = 0; i < count; ++i) {
6409 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
6410 types [i] = mono_reflection_type_get_handle (t, error);
6411 if (!types[i] || !is_ok (error)) {
6417 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
6420 gclass->type.type = res;
6424 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
6429 ves_icall_SymbolType_create_unmanaged_type (MonoReflectionType *type)
6432 mono_reflection_type_get_handle (type, &error);
6433 mono_error_set_pending_exception (&error);
6437 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
6439 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
6442 mono_error_init (error);
6444 MonoType *res = mono_reflection_type_get_handle (type, error);
6446 if (!res && is_ok (error)) {
6447 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
6449 return_val_if_nok (error, FALSE);
6451 klass = mono_class_from_mono_type (res);
6453 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
6454 mono_domain_lock (domain);
6456 if (!image_is_dynamic (klass->image)) {
6457 mono_class_setup_supertypes (klass);
6459 if (!domain->type_hash)
6460 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6461 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6462 mono_g_hash_table_insert (domain->type_hash, res, type);
6464 mono_domain_unlock (domain);
6465 mono_loader_unlock ();
6471 mono_reflection_register_with_runtime (MonoReflectionType *type)
6474 (void) reflection_register_with_runtime (type, &error);
6475 mono_error_set_pending_exception (&error);
6479 * LOCKING: Assumes the loader lock is held.
6481 static MonoMethodSignature*
6482 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
6483 MonoMethodSignature *sig;
6486 mono_error_init (error);
6488 count = parameters? mono_array_length (parameters): 0;
6490 sig = (MonoMethodSignature *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
6491 sig->param_count = count;
6492 sig->sentinelpos = -1; /* FIXME */
6493 for (i = 0; i < count; ++i) {
6494 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
6495 if (!is_ok (error)) {
6496 image_g_free (image, sig);
6504 * LOCKING: Assumes the loader lock is held.
6506 static MonoMethodSignature*
6507 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
6508 MonoMethodSignature *sig;
6510 mono_error_init (error);
6512 sig = parameters_to_signature (image, ctor->parameters, error);
6513 return_val_if_nok (error, NULL);
6514 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6515 sig->ret = &mono_defaults.void_class->byval_arg;
6520 * LOCKING: Assumes the loader lock is held.
6522 static MonoMethodSignature*
6523 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
6524 MonoMethodSignature *sig;
6526 mono_error_init (error);
6528 sig = parameters_to_signature (image, method->parameters, error);
6529 return_val_if_nok (error, NULL);
6530 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6531 if (method->rtype) {
6532 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
6533 if (!is_ok (error)) {
6534 image_g_free (image, sig);
6538 sig->ret = &mono_defaults.void_class->byval_arg;
6540 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6544 static MonoMethodSignature*
6545 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
6546 MonoMethodSignature *sig;
6548 mono_error_init (error);
6550 sig = parameters_to_signature (NULL, method->parameters, error);
6551 return_val_if_nok (error, NULL);
6552 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6553 if (method->rtype) {
6554 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
6555 if (!is_ok (error)) {
6560 sig->ret = &mono_defaults.void_class->byval_arg;
6562 sig->generic_param_count = 0;
6567 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
6569 mono_error_init (error);
6570 MonoClass *klass = mono_object_class (prop);
6571 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6572 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6573 *name = mono_string_to_utf8_checked (pb->name, error);
6574 return_if_nok (error);
6575 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
6577 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6578 *name = g_strdup (p->property->name);
6579 if (p->property->get)
6580 *type = mono_method_signature (p->property->get)->ret;
6582 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
6587 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
6589 mono_error_init (error);
6590 MonoClass *klass = mono_object_class (field);
6591 if (strcmp (klass->name, "FieldBuilder") == 0) {
6592 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6593 *name = mono_string_to_utf8_checked (fb->name, error);
6594 return_if_nok (error);
6595 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
6597 MonoReflectionField *f = (MonoReflectionField *)field;
6598 *name = g_strdup (mono_field_get_name (f->field));
6599 *type = f->field->type;
6603 #else /* DISABLE_REFLECTION_EMIT */
6606 mono_reflection_register_with_runtime (MonoReflectionType *type)
6612 is_sre_type_builder (MonoClass *klass)
6618 is_sre_generic_instance (MonoClass *klass)
6624 mono_is_sre_ctor_builder (MonoClass *klass)
6630 mono_is_sre_method_on_tb_inst (MonoClass *klass)
6636 mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
6642 init_type_builder_generics (MonoObject *type, MonoError *error)
6644 mono_error_init (error);
6647 #endif /* !DISABLE_REFLECTION_EMIT */
6651 is_sr_mono_field (MonoClass *klass)
6653 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
6657 mono_is_sr_mono_property (MonoClass *klass)
6659 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
6663 is_sr_mono_method (MonoClass *klass)
6665 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
6669 mono_is_sr_mono_cmethod (MonoClass *klass)
6671 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
6675 is_sr_mono_generic_method (MonoClass *klass)
6677 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
6681 is_sr_mono_generic_cmethod (MonoClass *klass)
6683 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
6687 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
6689 return is_sr_mono_method (klass) || mono_is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
6693 mono_is_sre_type_builder (MonoClass *klass)
6695 return is_sre_type_builder (klass);
6699 mono_is_sre_generic_instance (MonoClass *klass)
6701 return is_sre_generic_instance (klass);
6707 * encode_cattr_value:
6708 * Encode a value in a custom attribute stream of bytes.
6709 * The value to encode is either supplied as an object in argument val
6710 * (valuetypes are boxed), or as a pointer to the data in the
6712 * @type represents the type of the value
6713 * @buffer is the start of the buffer
6714 * @p the current position in the buffer
6715 * @buflen contains the size of the buffer and is used to return the new buffer size
6716 * if this needs to be realloced.
6717 * @retbuffer and @retp return the start and the position of the buffer
6718 * @error set on error.
6721 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
6723 MonoTypeEnum simple_type;
6725 mono_error_init (error);
6726 if ((p-buffer) + 10 >= *buflen) {
6729 newbuf = (char *)g_realloc (buffer, *buflen);
6730 p = newbuf + (p-buffer);
6734 argval = ((char*)arg + sizeof (MonoObject));
6735 simple_type = type->type;
6737 switch (simple_type) {
6738 case MONO_TYPE_BOOLEAN:
6743 case MONO_TYPE_CHAR:
6746 swap_with_size (p, argval, 2, 1);
6752 swap_with_size (p, argval, 4, 1);
6756 swap_with_size (p, argval, 8, 1);
6761 swap_with_size (p, argval, 8, 1);
6764 case MONO_TYPE_VALUETYPE:
6765 if (type->data.klass->enumtype) {
6766 simple_type = mono_class_enum_basetype (type->data.klass)->type;
6769 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6772 case MONO_TYPE_STRING: {
6779 str = mono_string_to_utf8_checked ((MonoString*)arg, error);
6780 return_if_nok (error);
6781 slen = strlen (str);
6782 if ((p-buffer) + 10 + slen >= *buflen) {
6786 newbuf = (char *)g_realloc (buffer, *buflen);
6787 p = newbuf + (p-buffer);
6790 mono_metadata_encode_value (slen, p, &p);
6791 memcpy (p, str, slen);
6796 case MONO_TYPE_CLASS: {
6805 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
6806 return_if_nok (error);
6808 str = type_get_qualified_name (arg_type, NULL);
6809 slen = strlen (str);
6810 if ((p-buffer) + 10 + slen >= *buflen) {
6814 newbuf = (char *)g_realloc (buffer, *buflen);
6815 p = newbuf + (p-buffer);
6818 mono_metadata_encode_value (slen, p, &p);
6819 memcpy (p, str, slen);
6824 case MONO_TYPE_SZARRAY: {
6826 MonoClass *eclass, *arg_eclass;
6829 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6832 len = mono_array_length ((MonoArray*)arg);
6834 *p++ = (len >> 8) & 0xff;
6835 *p++ = (len >> 16) & 0xff;
6836 *p++ = (len >> 24) & 0xff;
6838 *retbuffer = buffer;
6839 eclass = type->data.klass;
6840 arg_eclass = mono_object_class (arg)->element_class;
6843 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
6844 eclass = mono_defaults.object_class;
6846 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
6847 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6848 int elsize = mono_class_array_element_size (arg_eclass);
6849 for (i = 0; i < len; ++i) {
6850 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
6851 return_if_nok (error);
6854 } else if (eclass->valuetype && arg_eclass->valuetype) {
6855 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6856 int elsize = mono_class_array_element_size (eclass);
6857 for (i = 0; i < len; ++i) {
6858 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
6859 return_if_nok (error);
6863 for (i = 0; i < len; ++i) {
6864 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
6865 return_if_nok (error);
6870 case MONO_TYPE_OBJECT: {
6876 * The parameter type is 'object' but the type of the actual
6877 * argument is not. So we have to add type information to the blob
6878 * too. This is completely undocumented in the spec.
6882 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
6887 klass = mono_object_class (arg);
6889 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
6893 return_if_nok (error);
6896 if (klass->enumtype) {
6898 } else if (klass == mono_defaults.string_class) {
6899 simple_type = MONO_TYPE_STRING;
6902 } else if (klass->rank == 1) {
6904 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
6905 /* See Partition II, Appendix B3 */
6908 *p++ = klass->element_class->byval_arg.type;
6909 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
6910 return_if_nok (error);
6912 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6913 *p++ = simple_type = klass->byval_arg.type;
6916 g_error ("unhandled type in custom attr");
6918 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
6919 slen = strlen (str);
6920 if ((p-buffer) + 10 + slen >= *buflen) {
6924 newbuf = (char *)g_realloc (buffer, *buflen);
6925 p = newbuf + (p-buffer);
6928 mono_metadata_encode_value (slen, p, &p);
6929 memcpy (p, str, slen);
6932 simple_type = mono_class_enum_basetype (klass)->type;
6936 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6939 *retbuffer = buffer;
6943 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
6945 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
6946 char *str = type_get_qualified_name (type, NULL);
6947 int slen = strlen (str);
6951 * This seems to be optional...
6954 mono_metadata_encode_value (slen, p, &p);
6955 memcpy (p, str, slen);
6958 } else if (type->type == MONO_TYPE_OBJECT) {
6960 } else if (type->type == MONO_TYPE_CLASS) {
6961 /* it should be a type: encode_cattr_value () has the check */
6964 mono_metadata_encode_value (type->type, p, &p);
6965 if (type->type == MONO_TYPE_SZARRAY)
6966 /* See the examples in Partition VI, Annex B */
6967 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
6973 #ifndef DISABLE_REFLECTION_EMIT
6975 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
6979 mono_error_init (error);
6981 /* Preallocate a large enough buffer */
6982 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
6983 char *str = type_get_qualified_name (type, NULL);
6986 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
6987 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
6993 len += strlen (name);
6995 if ((p-buffer) + 20 + len >= *buflen) {
6999 newbuf = (char *)g_realloc (buffer, *buflen);
7000 p = newbuf + (p-buffer);
7004 encode_field_or_prop_type (type, p, &p);
7006 len = strlen (name);
7007 mono_metadata_encode_value (len, p, &p);
7008 memcpy (p, name, len);
7010 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
7011 return_if_nok (error);
7013 *retbuffer = buffer;
7017 * mono_reflection_get_custom_attrs_blob:
7018 * @ctor: custom attribute constructor
7019 * @ctorArgs: arguments o the constructor
7025 * Creates the blob of data that needs to be saved in the metadata and that represents
7026 * the custom attributed described by @ctor, @ctorArgs etc.
7027 * Returns: a Byte array representing the blob of data.
7030 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7033 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
7034 mono_error_cleanup (&error);
7039 * mono_reflection_get_custom_attrs_blob_checked:
7040 * @ctor: custom attribute constructor
7041 * @ctorArgs: arguments o the constructor
7046 * @error: set on error
7048 * Creates the blob of data that needs to be saved in the metadata and that represents
7049 * the custom attributed described by @ctor, @ctorArgs etc.
7050 * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
7053 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
7055 MonoArray *result = NULL;
7056 MonoMethodSignature *sig;
7061 mono_error_init (error);
7063 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7064 /* sig is freed later so allocate it in the heap */
7065 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
7066 if (!is_ok (error)) {
7071 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7074 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7076 p = buffer = (char *)g_malloc (buflen);
7077 /* write the prolog */
7080 for (i = 0; i < sig->param_count; ++i) {
7081 arg = mono_array_get (ctorArgs, MonoObject*, i);
7082 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
7083 if (!is_ok (error)) goto leave;
7087 i += mono_array_length (properties);
7089 i += mono_array_length (fields);
7091 *p++ = (i >> 8) & 0xff;
7094 for (i = 0; i < mono_array_length (properties); ++i) {
7098 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
7099 get_prop_name_and_type (prop, &pname, &ptype, error);
7100 if (!is_ok (error)) goto leave;
7101 *p++ = 0x54; /* PROPERTY signature */
7102 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
7104 if (!is_ok (error)) goto leave;
7110 for (i = 0; i < mono_array_length (fields); ++i) {
7114 field = (MonoObject *)mono_array_get (fields, gpointer, i);
7115 get_field_name_and_type (field, &fname, &ftype, error);
7116 if (!is_ok (error)) goto leave;
7117 *p++ = 0x53; /* FIELD signature */
7118 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
7120 if (!is_ok (error)) goto leave;
7124 g_assert (p - buffer <= buflen);
7125 buflen = p - buffer;
7126 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
7129 p = mono_array_addr (result, char, 0);
7130 memcpy (p, buffer, buflen);
7133 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7139 * reflection_setup_internal_class:
7140 * @tb: a TypeBuilder object
7141 * @error: set on error
7143 * Creates a MonoClass that represents the TypeBuilder.
7144 * This is a trick that lets us simplify a lot of reflection code
7145 * (and will allow us to support Build and Run assemblies easier).
7147 * Returns TRUE on success. On failure, returns FALSE and sets @error.
7150 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
7152 MonoClass *klass, *parent;
7154 mono_error_init (error);
7155 RESOLVE_TYPE (tb->parent, error);
7156 return_val_if_nok (error, FALSE);
7158 mono_loader_lock ();
7161 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
7162 if (!is_ok (error)) {
7163 mono_loader_unlock ();
7166 /* check so we can compile corlib correctly */
7167 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7168 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7169 parent = parent_type->data.klass;
7171 parent = mono_class_from_mono_type (parent_type);
7177 /* the type has already being created: it means we just have to change the parent */
7178 if (tb->type.type) {
7179 klass = mono_class_from_mono_type (tb->type.type);
7180 klass->parent = NULL;
7181 /* fool mono_class_setup_parent */
7182 klass->supertypes = NULL;
7183 mono_class_setup_parent (klass, parent);
7184 mono_class_setup_mono_type (klass);
7185 mono_loader_unlock ();
7189 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
7191 klass->image = &tb->module->dynamic_image->image;
7193 klass->inited = 1; /* we lie to the runtime */
7194 klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
7197 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
7200 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7201 klass->flags = tb->attrs;
7203 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
7205 klass->element_class = klass;
7207 if (mono_class_get_ref_info (klass) == NULL) {
7209 mono_class_set_ref_info (klass, tb);
7211 /* Put into cache so mono_class_get_checked () will find it.
7212 Skip nested types as those should not be available on the global scope. */
7213 if (!tb->nesting_type)
7214 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7217 We must register all types as we cannot rely on the name_cache hashtable since we find the class
7218 by performing a mono_class_get which does the full resolution.
7220 Working around this semantics would require us to write a lot of code for no clear advantage.
7222 mono_image_append_class_to_reflection_info_set (klass);
7224 g_assert (mono_class_get_ref_info (klass) == tb);
7227 mono_dynamic_image_register_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
7229 if (parent != NULL) {
7230 mono_class_setup_parent (klass, parent);
7231 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7232 const char *old_n = klass->name;
7233 /* trick to get relative numbering right when compiling corlib */
7234 klass->name = "BuildingObject";
7235 mono_class_setup_parent (klass, mono_defaults.object_class);
7236 klass->name = old_n;
7239 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7240 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7241 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7242 klass->instance_size = sizeof (MonoObject);
7243 klass->size_inited = 1;
7244 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
7247 mono_class_setup_mono_type (klass);
7249 mono_class_setup_supertypes (klass);
7252 * FIXME: handle interfaces.
7255 tb->type.type = &klass->byval_arg;
7257 if (tb->nesting_type) {
7258 g_assert (tb->nesting_type->type);
7259 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
7260 if (!is_ok (error)) goto failure;
7261 klass->nested_in = mono_class_from_mono_type (nesting_type);
7264 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7266 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
7268 mono_loader_unlock ();
7272 mono_loader_unlock ();
7277 * ves_icall_TypeBuilder_setup_internal_class:
7278 * @tb: a TypeBuilder object
7281 * Creates a MonoClass that represents the TypeBuilder.
7282 * This is a trick that lets us simplify a lot of reflection code
7283 * (and will allow us to support Build and Run assemblies easier).
7287 ves_icall_TypeBuilder_setup_internal_class (MonoReflectionTypeBuilder *tb)
7290 (void) reflection_setup_internal_class (tb, &error);
7291 mono_error_set_pending_exception (&error);
7295 * ves_icall_TypeBuilder_setup_generic_class:
7296 * @tb: a TypeBuilder object
7298 * Setup the generic class before adding the first generic parameter.
7301 ves_icall_TypeBuilder_setup_generic_class (MonoReflectionTypeBuilder *tb)
7306 * mono_reflection_create_generic_class:
7307 * @tb: a TypeBuilder object
7308 * @error: set on error
7310 * Creates the generic class after all generic parameters have been added.
7311 * On success returns TRUE, on failure returns FALSE and sets @error.
7315 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
7321 mono_error_init (error);
7323 klass = mono_class_from_mono_type (tb->type.type);
7325 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7327 if (klass->generic_container || (count == 0))
7330 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
7332 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
7334 klass->generic_container->owner.klass = klass;
7335 klass->generic_container->type_argc = count;
7336 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
7338 klass->is_generic = 1;
7340 for (i = 0; i < count; i++) {
7341 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
7342 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
7343 return_val_if_nok (error, FALSE);
7344 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
7345 klass->generic_container->type_params [i] = *param;
7346 /*Make sure we are a diferent type instance */
7347 klass->generic_container->type_params [i].param.owner = klass->generic_container;
7348 klass->generic_container->type_params [i].info.pklass = NULL;
7349 klass->generic_container->type_params [i].info.flags = gparam->attrs;
7351 g_assert (klass->generic_container->type_params [i].param.owner);
7354 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
7359 * reflection_create_internal_class:
7360 * @tb: a TypeBuilder object
7361 * @error: set on error
7363 * Actually create the MonoClass that is associated with the TypeBuilder.
7364 * On success returns TRUE, on failure returns FALSE and sets @error.
7368 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
7372 mono_error_init (error);
7373 klass = mono_class_from_mono_type (tb->type.type);
7375 mono_loader_lock ();
7376 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
7377 MonoReflectionFieldBuilder *fb;
7379 MonoType *enum_basetype;
7381 g_assert (tb->fields != NULL);
7382 g_assert (mono_array_length (tb->fields) >= 1);
7384 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7386 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
7387 if (!is_ok (error)) {
7388 mono_loader_unlock ();
7391 if (!mono_type_is_valid_enum_basetype (field_type)) {
7392 mono_loader_unlock ();
7396 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
7397 if (!is_ok (error)) {
7398 mono_loader_unlock ();
7401 klass->element_class = mono_class_from_mono_type (enum_basetype);
7402 if (!klass->element_class)
7403 klass->element_class = mono_class_from_mono_type (enum_basetype);
7406 * get the element_class from the current corlib.
7408 ec = default_class_from_mono_type (enum_basetype);
7409 klass->instance_size = ec->instance_size;
7410 klass->size_inited = 1;
7412 * this is almost safe to do with enums and it's needed to be able
7413 * to create objects of the enum type (for use in SetConstant).
7415 /* FIXME: Does this mean enums can't have method overrides ? */
7416 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
7418 mono_loader_unlock ();
7423 * ves_icall_TypeBuilder_create_internal_class:
7424 * @tb: a TypeBuilder object
7427 * Actually create the MonoClass that is associated with the TypeBuilder.
7430 ves_icall_TypeBuilder_create_internal_class (MonoReflectionTypeBuilder *tb)
7433 (void) reflection_create_internal_class (tb, &error);
7434 mono_error_set_pending_exception (&error);
7437 static MonoMarshalSpec*
7438 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
7439 MonoReflectionMarshal *minfo, MonoError *error)
7441 MonoMarshalSpec *res;
7443 mono_error_init (error);
7445 res = image_g_new0 (image, MonoMarshalSpec, 1);
7446 res->native = (MonoMarshalNative)minfo->type;
7448 switch (minfo->type) {
7449 case MONO_NATIVE_LPARRAY:
7450 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
7451 if (minfo->has_size) {
7452 res->data.array_data.param_num = minfo->param_num;
7453 res->data.array_data.num_elem = minfo->count;
7454 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
7457 res->data.array_data.param_num = -1;
7458 res->data.array_data.num_elem = -1;
7459 res->data.array_data.elem_mult = -1;
7463 case MONO_NATIVE_BYVALTSTR:
7464 case MONO_NATIVE_BYVALARRAY:
7465 res->data.array_data.num_elem = minfo->count;
7468 case MONO_NATIVE_CUSTOM:
7469 if (minfo->marshaltyperef) {
7470 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
7471 if (!is_ok (error)) {
7472 image_g_free (image, res);
7475 res->data.custom_data.custom_name =
7476 type_get_fully_qualified_name (marshaltyperef);
7478 if (minfo->mcookie) {
7479 res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
7480 if (!is_ok (error)) {
7481 image_g_free (image, res);
7493 #endif /* !DISABLE_REFLECTION_EMIT */
7495 MonoReflectionMarshalAsAttribute*
7496 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7497 MonoMarshalSpec *spec, MonoError *error)
7499 MonoReflectionType *rt;
7500 MonoReflectionMarshalAsAttribute *minfo;
7503 mono_error_init (error);
7505 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
7508 minfo->utype = spec->native;
7510 switch (minfo->utype) {
7511 case MONO_NATIVE_LPARRAY:
7512 minfo->array_subtype = spec->data.array_data.elem_type;
7513 minfo->size_const = spec->data.array_data.num_elem;
7514 if (spec->data.array_data.param_num != -1)
7515 minfo->size_param_index = spec->data.array_data.param_num;
7518 case MONO_NATIVE_BYVALTSTR:
7519 case MONO_NATIVE_BYVALARRAY:
7520 minfo->size_const = spec->data.array_data.num_elem;
7523 case MONO_NATIVE_CUSTOM:
7524 if (spec->data.custom_data.custom_name) {
7525 mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
7526 return_val_if_nok (error, NULL);
7529 rt = mono_type_get_object_checked (domain, mtype, error);
7533 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
7536 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
7538 if (spec->data.custom_data.cookie)
7539 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
7549 #ifndef DISABLE_REFLECTION_EMIT
7551 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7552 ReflectionMethodBuilder *rmb,
7553 MonoMethodSignature *sig,
7557 MonoMethodWrapper *wrapperm;
7558 MonoMarshalSpec **specs;
7559 MonoReflectionMethodAux *method_aux;
7564 mono_error_init (error);
7566 * Methods created using a MethodBuilder should have their memory allocated
7567 * inside the image mempool, while dynamic methods should have their memory
7570 dynamic = rmb->refs != NULL;
7571 image = dynamic ? NULL : klass->image;
7574 g_assert (!klass->generic_class);
7576 mono_loader_lock ();
7578 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7579 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7580 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
7582 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
7584 wrapperm = (MonoMethodWrapper*)m;
7586 m->dynamic = dynamic;
7588 m->flags = rmb->attrs;
7589 m->iflags = rmb->iattrs;
7590 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
7593 m->sre_method = TRUE;
7594 m->skip_visibility = rmb->skip_visibility;
7596 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7598 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7599 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7602 m->signature->pinvoke = 1;
7603 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7604 m->signature->pinvoke = 1;
7606 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
7608 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
7609 mono_error_assert_ok (error);
7610 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
7611 mono_error_assert_ok (error);
7613 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
7615 if (image_is_dynamic (klass->image))
7616 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7618 mono_loader_unlock ();
7621 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7622 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7623 MonoMethodHeader *header;
7625 gint32 max_stack, i;
7626 gint32 num_locals = 0;
7627 gint32 num_clauses = 0;
7631 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7632 code_size = rmb->ilgen->code_len;
7633 max_stack = rmb->ilgen->max_stack;
7634 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7635 if (rmb->ilgen->ex_handlers)
7636 num_clauses = method_count_clauses (rmb->ilgen);
7639 code = mono_array_addr (rmb->code, guint8, 0);
7640 code_size = mono_array_length (rmb->code);
7641 /* we probably need to run a verifier on the code... */
7651 header = (MonoMethodHeader *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
7652 header->code_size = code_size;
7653 header->code = (const unsigned char *)image_g_malloc (image, code_size);
7654 memcpy ((char*)header->code, code, code_size);
7655 header->max_stack = max_stack;
7656 header->init_locals = rmb->init_locals;
7657 header->num_locals = num_locals;
7659 for (i = 0; i < num_locals; ++i) {
7660 MonoReflectionLocalBuilder *lb =
7661 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7663 header->locals [i] = image_g_new0 (image, MonoType, 1);
7664 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
7665 mono_error_assert_ok (error);
7666 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
7669 header->num_clauses = num_clauses;
7671 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
7672 rmb->ilgen, num_clauses, error);
7673 mono_error_assert_ok (error);
7676 wrapperm->header = header;
7679 if (rmb->generic_params) {
7680 int count = mono_array_length (rmb->generic_params);
7681 MonoGenericContainer *container = rmb->generic_container;
7683 g_assert (container);
7685 container->type_argc = count;
7686 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
7687 container->owner.method = m;
7688 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
7690 m->is_generic = TRUE;
7691 mono_method_set_generic_container (m, container);
7693 for (i = 0; i < count; i++) {
7694 MonoReflectionGenericParam *gp =
7695 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7696 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
7697 mono_error_assert_ok (error);
7698 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
7699 container->type_params [i] = *param;
7703 * The method signature might have pointers to generic parameters that belong to other methods.
7704 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
7705 * generic parameters.
7707 for (i = 0; i < m->signature->param_count; ++i) {
7708 MonoType *t = m->signature->params [i];
7709 if (t->type == MONO_TYPE_MVAR) {
7710 MonoGenericParam *gparam = t->data.generic_param;
7711 if (gparam->num < count) {
7712 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
7713 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
7719 if (klass->generic_container) {
7720 container->parent = klass->generic_container;
7721 container->context.class_inst = klass->generic_container->context.class_inst;
7723 container->context.method_inst = mono_get_shared_generic_inst (container);
7727 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7731 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7733 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
7734 data [0] = GUINT_TO_POINTER (rmb->nrefs);
7735 for (i = 0; i < rmb->nrefs; ++i)
7736 data [i + 1] = rmb->refs [i];
7741 /* Parameter info */
7744 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
7745 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
7746 for (i = 0; i <= m->signature->param_count; ++i) {
7747 MonoReflectionParamBuilder *pb;
7748 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7749 if ((i > 0) && (pb->attrs)) {
7750 /* Make a copy since it might point to a shared type structure */
7751 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
7752 m->signature->params [i - 1]->attrs = pb->attrs;
7755 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
7756 MonoDynamicImage *assembly;
7758 MonoTypeEnum def_type;
7762 if (!method_aux->param_defaults) {
7763 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
7764 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
7766 assembly = (MonoDynamicImage*)klass->image;
7767 idx = encode_constant (assembly, pb->def_value, &def_type);
7768 /* Copy the data from the blob since it might get realloc-ed */
7769 p = assembly->blob.data + idx;
7770 len = mono_metadata_decode_blob_size (p, &p2);
7772 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
7773 method_aux->param_default_types [i] = def_type;
7774 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7778 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
7779 mono_error_assert_ok (error);
7782 if (!method_aux->param_cattr)
7783 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
7784 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
7790 /* Parameter marshalling */
7793 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7794 MonoReflectionParamBuilder *pb;
7795 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7796 if (pb->marshal_info) {
7798 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
7799 specs [pb->position] =
7800 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
7801 if (!is_ok (error)) {
7802 mono_loader_unlock ();
7803 image_g_free (image, specs);
7804 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
7810 if (specs != NULL) {
7812 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
7813 method_aux->param_marshall = specs;
7816 if (image_is_dynamic (klass->image) && method_aux)
7817 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7819 mono_loader_unlock ();
7825 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
7827 ReflectionMethodBuilder rmb;
7828 MonoMethodSignature *sig;
7830 mono_loader_lock ();
7831 g_assert (klass->image != NULL);
7832 sig = ctor_builder_to_signature (klass->image, mb, error);
7833 mono_loader_unlock ();
7834 return_val_if_nok (error, NULL);
7836 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
7839 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
7840 return_val_if_nok (error, NULL);
7841 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7843 /* If we are in a generic class, we might be called multiple times from inflate_method */
7844 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
7845 /* ilgen is no longer needed */
7853 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
7855 ReflectionMethodBuilder rmb;
7856 MonoMethodSignature *sig;
7858 mono_error_init (error);
7860 mono_loader_lock ();
7861 g_assert (klass->image != NULL);
7862 sig = method_builder_to_signature (klass->image, mb, error);
7863 mono_loader_unlock ();
7864 return_val_if_nok (error, NULL);
7866 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
7869 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
7870 return_val_if_nok (error, NULL);
7871 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7873 /* If we are in a generic class, we might be called multiple times from inflate_method */
7874 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
7875 /* ilgen is no longer needed */
7881 static MonoClassField*
7882 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
7884 MonoClassField *field;
7887 mono_error_init (error);
7889 field = g_new0 (MonoClassField, 1);
7891 field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
7892 mono_error_assert_ok (error);
7893 if (fb->attrs || fb->modreq || fb->modopt) {
7894 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
7895 if (!is_ok (error)) {
7899 field->type = mono_metadata_type_dup (NULL, type);
7900 field->type->attrs = fb->attrs;
7902 g_assert (image_is_dynamic (klass->image));
7903 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
7904 g_free (field->type);
7905 if (!is_ok (error)) {
7909 field->type = mono_metadata_type_dup (klass->image, custom);
7912 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
7913 if (!is_ok (error)) {
7918 if (fb->offset != -1)
7919 field->offset = fb->offset;
7920 field->parent = klass;
7921 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7923 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
7929 #ifndef DISABLE_REFLECTION_EMIT
7932 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
7934 MonoMethodInflated *imethod;
7935 MonoGenericContext *context;
7939 * With generic code sharing the klass might not be inflated.
7940 * This can happen because classes inflated with their own
7941 * type arguments are "normalized" to the uninflated class.
7943 if (!klass->generic_class)
7946 context = mono_class_get_context (klass);
7948 if (klass->method.count && klass->methods) {
7949 /* Find the already created inflated method */
7950 for (i = 0; i < klass->method.count; ++i) {
7951 g_assert (klass->methods [i]->is_inflated);
7952 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
7955 g_assert (i < klass->method.count);
7956 imethod = (MonoMethodInflated*)klass->methods [i];
7959 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
7960 mono_error_assert_ok (&error);
7963 if (method->is_generic && image_is_dynamic (method->klass->image)) {
7964 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
7966 mono_image_lock ((MonoImage*)image);
7967 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
7968 mono_image_unlock ((MonoImage*)image);
7970 return (MonoMethod *) imethod;
7974 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
7979 mono_error_init (error);
7981 MonoClass *type_class = mono_object_class (type);
7983 if (is_sre_generic_instance (type_class)) {
7984 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
7985 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
7986 return_val_if_nok (error, NULL);
7987 gklass = mono_class_from_mono_type (generic_type);
7988 } else if (is_sre_type_builder (type_class)) {
7989 MonoType *t = mono_reflection_type_get_handle (type, error);
7990 return_val_if_nok (error, NULL);
7991 gklass = mono_class_from_mono_type (t);
7992 } else if (type->type) {
7993 gklass = mono_class_from_mono_type (type->type);
7994 gklass = mono_class_get_generic_type_definition (gklass);
7996 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
7999 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8000 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
8001 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
8003 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
8007 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
8008 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
8011 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8012 method = ((MonoReflectionMethod *) obj)->method;
8014 method = NULL; /* prevent compiler warning */
8015 g_error ("can't handle type %s", obj->vtable->klass->name);
8018 MonoType *t = mono_reflection_type_get_handle (type, error);
8019 return_val_if_nok (error, NULL);
8020 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
8023 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
8025 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
8027 MonoGenericClass *gclass;
8028 MonoDynamicGenericClass *dgclass;
8029 MonoClass *klass, *gklass;
8033 mono_error_init (error);
8035 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
8036 return_val_if_nok (error, FALSE);
8037 klass = mono_class_from_mono_type (gtype);
8038 g_assert (gtype->type == MONO_TYPE_GENERICINST);
8039 gclass = gtype->data.generic_class;
8041 if (!gclass->is_dynamic)
8044 dgclass = (MonoDynamicGenericClass *) gclass;
8046 if (dgclass->initialized)
8049 gklass = gclass->container_class;
8050 mono_class_init (gklass);
8052 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8054 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
8055 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
8056 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
8058 for (i = 0; i < dgclass->count_fields; i++) {
8059 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
8060 MonoClassField *field, *inflated_field = NULL;
8062 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
8063 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
8064 return_val_if_nok (error, FALSE);
8065 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8066 field = ((MonoReflectionField *) obj)->field;
8068 field = NULL; /* prevent compiler warning */
8069 g_assert_not_reached ();
8072 dgclass->fields [i] = *field;
8073 dgclass->fields [i].parent = klass;
8074 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
8075 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
8076 mono_error_assert_ok (error); /* FIXME don't swallow the error */
8077 dgclass->field_generic_types [i] = field->type;
8078 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
8079 dgclass->field_objects [i] = obj;
8081 if (inflated_field) {
8082 g_free (inflated_field);
8084 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
8088 dgclass->initialized = TRUE;
8093 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
8096 (void) reflection_generic_class_initialize (type, fields, &error);
8097 mono_error_set_pending_exception (&error);
8101 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
8103 MonoDynamicGenericClass *dgclass;
8106 g_assert (gclass->is_dynamic);
8108 dgclass = (MonoDynamicGenericClass *)gclass;
8110 for (i = 0; i < dgclass->count_fields; ++i) {
8111 MonoClassField *field = dgclass->fields + i;
8112 mono_metadata_free_type (field->type);
8113 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
8118 * fix_partial_generic_class:
8119 * @klass: a generic instantiation MonoClass
8120 * @error: set on error
8122 * Assumes that the generic container of @klass has its vtable
8123 * initialized, and updates the parent class, insterfaces, methods and
8124 * fields of @klass by inflating the types using the generic context.
8126 * On success returns TRUE, on failure returns FALSE and sets @error.
8130 fix_partial_generic_class (MonoClass *klass, MonoError *error)
8132 MonoClass *gklass = klass->generic_class->container_class;
8133 MonoDynamicGenericClass *dgclass;
8136 mono_error_init (error);
8138 if (klass->wastypebuilder)
8141 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
8142 if (klass->parent != gklass->parent) {
8143 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
8144 if (mono_error_ok (error)) {
8145 MonoClass *parent = mono_class_from_mono_type (parent_type);
8146 mono_metadata_free_type (parent_type);
8147 if (parent != klass->parent) {
8148 /*fool mono_class_setup_parent*/
8149 klass->supertypes = NULL;
8150 mono_class_setup_parent (klass, parent);
8153 if (gklass->wastypebuilder)
8154 klass->wastypebuilder = TRUE;
8159 if (!dgclass->initialized)
8162 if (klass->method.count != gklass->method.count) {
8163 klass->method.count = gklass->method.count;
8164 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
8166 for (i = 0; i < klass->method.count; i++) {
8167 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
8168 gklass->methods [i], klass, mono_class_get_context (klass), error);
8169 mono_error_assert_ok (error);
8173 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
8174 klass->interface_count = gklass->interface_count;
8175 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
8176 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
8178 for (i = 0; i < gklass->interface_count; ++i) {
8179 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
8180 return_val_if_nok (error, FALSE);
8182 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
8183 mono_metadata_free_type (iface_type);
8185 if (!ensure_runtime_vtable (klass->interfaces [i], error))
8188 klass->interfaces_inited = 1;
8191 if (klass->field.count != gklass->field.count) {
8192 klass->field.count = gklass->field.count;
8193 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
8195 for (i = 0; i < klass->field.count; i++) {
8196 klass->fields [i] = gklass->fields [i];
8197 klass->fields [i].parent = klass;
8198 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
8199 return_val_if_nok (error, FALSE);
8203 /*We can only finish with this klass once it's parent has as well*/
8204 if (gklass->wastypebuilder)
8205 klass->wastypebuilder = TRUE;
8210 * ensure_generic_class_runtime_vtable:
8211 * @klass a generic class
8212 * @error set on error
8214 * Ensures that the generic container of @klass has a vtable and
8215 * returns TRUE on success. On error returns FALSE and sets @error.
8218 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
8220 MonoClass *gklass = klass->generic_class->container_class;
8222 mono_error_init (error);
8224 if (!ensure_runtime_vtable (gklass, error))
8227 return fix_partial_generic_class (klass, error);
8231 * ensure_runtime_vtable:
8233 * @error set on error
8235 * Ensures that @klass has a vtable and returns TRUE on success. On
8236 * error returns FALSE and sets @error.
8239 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
8241 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
8244 mono_error_init (error);
8246 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
8249 if (!ensure_runtime_vtable (klass->parent, error))
8253 num = tb->ctors? mono_array_length (tb->ctors): 0;
8254 num += tb->num_methods;
8255 klass->method.count = num;
8256 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
8257 num = tb->ctors? mono_array_length (tb->ctors): 0;
8258 for (i = 0; i < num; ++i) {
8259 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
8262 klass->methods [i] = ctor;
8264 num = tb->num_methods;
8266 for (i = 0; i < num; ++i) {
8267 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
8270 klass->methods [j++] = meth;
8273 if (tb->interfaces) {
8274 klass->interface_count = mono_array_length (tb->interfaces);
8275 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
8276 for (i = 0; i < klass->interface_count; ++i) {
8277 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
8278 return_val_if_nok (error, FALSE);
8279 klass->interfaces [i] = mono_class_from_mono_type (iface);
8280 if (!ensure_runtime_vtable (klass->interfaces [i], error))
8283 klass->interfaces_inited = 1;
8285 } else if (klass->generic_class){
8286 if (!ensure_generic_class_runtime_vtable (klass, error)) {
8287 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
8292 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
8294 for (i = 0; i < klass->method.count; ++i) {
8295 MonoMethod *im = klass->methods [i];
8296 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
8297 im->slot = slot_num++;
8300 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
8301 mono_class_setup_interface_offsets (klass);
8302 mono_class_setup_interface_id (klass);
8306 * The generic vtable is needed even if image->run is not set since some
8307 * runtime code like ves_icall_Type_GetMethodsByName depends on
8308 * method->slot being defined.
8312 * tb->methods could not be freed since it is used for determining
8313 * overrides during dynamic vtable construction.
8320 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
8322 mono_error_init (error);
8323 MonoClass *klass = mono_object_class (method);
8324 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
8325 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
8326 return sr_method->method;
8328 if (is_sre_method_builder (klass)) {
8329 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
8332 if (mono_is_sre_method_on_tb_inst (klass)) {
8333 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
8335 /*FIXME move this to a proper method and unify with resolve_object*/
8336 if (m->method_args) {
8337 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
8339 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
8340 return_val_if_nok (error, NULL);
8341 MonoClass *inflated_klass = mono_class_from_mono_type (type);
8342 MonoMethod *mono_method;
8344 if (is_sre_method_builder (mono_object_class (m->mb)))
8345 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
8346 else if (is_sr_mono_method (mono_object_class (m->mb)))
8347 mono_method = ((MonoReflectionMethod *)m->mb)->method;
8349 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)));
8351 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
8356 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
8361 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
8363 MonoReflectionTypeBuilder *tb;
8365 MonoReflectionMethod *m;
8367 mono_error_init (error);
8371 g_assert (image_is_dynamic (klass->image));
8373 if (!mono_class_get_ref_info (klass))
8376 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
8378 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
8382 for (i = 0; i < tb->num_methods; ++i) {
8383 MonoReflectionMethodBuilder *mb =
8384 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8385 if (mb->override_methods)
8386 onum += mono_array_length (mb->override_methods);
8391 *overrides = g_new0 (MonoMethod*, onum * 2);
8394 for (i = 0; i < tb->num_methods; ++i) {
8395 MonoReflectionMethodBuilder *mb =
8396 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8397 if (mb->override_methods) {
8398 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
8399 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
8401 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
8402 return_if_nok (error);
8403 (*overrides) [onum * 2 + 1] = mb->mhandle;
8405 g_assert (mb->mhandle);
8413 *num_overrides = onum;
8417 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
8419 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
8420 MonoReflectionFieldBuilder *fb;
8421 MonoClassField *field;
8422 MonoImage *image = klass->image;
8425 guint32 len, idx, real_size = 0;
8427 klass->field.count = tb->num_fields;
8428 klass->field.first = 0;
8430 mono_error_init (error);
8432 if (tb->class_size) {
8433 if ((tb->packing_size & 0xffffff00) != 0) {
8434 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
8435 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
8438 klass->packing_size = tb->packing_size;
8439 real_size = klass->instance_size + tb->class_size;
8442 if (!klass->field.count) {
8443 klass->instance_size = MAX (klass->instance_size, real_size);
8447 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
8448 mono_class_alloc_ext (klass);
8449 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
8451 This is, guess what, a hack.
8452 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
8453 On the static path no field class is resolved, only types are built. This is the right thing to do
8455 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
8457 klass->size_inited = 1;
8459 for (i = 0; i < klass->field.count; ++i) {
8460 MonoArray *rva_data;
8461 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
8462 field = &klass->fields [i];
8463 field->name = mono_string_to_utf8_image (image, fb->name, error);
8464 if (!mono_error_ok (error))
8467 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
8468 return_if_nok (error);
8469 field->type = mono_metadata_type_dup (klass->image, type);
8470 field->type->attrs = fb->attrs;
8472 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
8473 return_if_nok (error);
8476 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
8477 char *base = mono_array_addr (rva_data, char, 0);
8478 size_t size = mono_array_length (rva_data);
8479 char *data = (char *)mono_image_alloc (klass->image, size);
8480 memcpy (data, base, size);
8481 klass->ext->field_def_values [i].data = data;
8483 if (fb->offset != -1)
8484 field->offset = fb->offset;
8485 field->parent = klass;
8487 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8489 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
8490 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
8492 if (fb->def_value) {
8493 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8494 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8495 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
8496 /* Copy the data from the blob since it might get realloc-ed */
8497 p = assembly->blob.data + idx;
8498 len = mono_metadata_decode_blob_size (p, &p2);
8500 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
8501 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
8505 klass->instance_size = MAX (klass->instance_size, real_size);
8506 mono_class_layout_fields (klass, klass->instance_size);
8510 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
8512 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
8513 MonoReflectionPropertyBuilder *pb;
8514 MonoImage *image = klass->image;
8515 MonoProperty *properties;
8518 mono_error_init (error);
8521 klass->ext = image_g_new0 (image, MonoClassExt, 1);
8523 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8524 klass->ext->property.first = 0;
8526 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
8527 klass->ext->properties = properties;
8528 for (i = 0; i < klass->ext->property.count; ++i) {
8529 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8530 properties [i].parent = klass;
8531 properties [i].attrs = pb->attrs;
8532 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
8533 if (!mono_error_ok (error))
8536 properties [i].get = pb->get_method->mhandle;
8538 properties [i].set = pb->set_method->mhandle;
8540 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
8541 if (pb->def_value) {
8544 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8545 if (!klass->ext->prop_def_values)
8546 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
8547 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
8548 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
8549 /* Copy the data from the blob since it might get realloc-ed */
8550 p = assembly->blob.data + idx;
8551 len = mono_metadata_decode_blob_size (p, &p2);
8553 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
8554 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
8559 static MonoReflectionEvent *
8560 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
8562 mono_error_init (error);
8564 MonoEvent *event = g_new0 (MonoEvent, 1);
8567 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
8568 if (!is_ok (error)) {
8572 klass = mono_class_from_mono_type (type);
8574 event->parent = klass;
8575 event->attrs = eb->attrs;
8576 event->name = mono_string_to_utf8_checked (eb->name, error);
8577 if (!is_ok (error)) {
8582 event->add = eb->add_method->mhandle;
8583 if (eb->remove_method)
8584 event->remove = eb->remove_method->mhandle;
8585 if (eb->raise_method)
8586 event->raise = eb->raise_method->mhandle;
8588 #ifndef MONO_SMALL_CONFIG
8589 if (eb->other_methods) {
8591 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8592 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8593 MonoReflectionMethodBuilder *mb =
8594 mono_array_get (eb->other_methods,
8595 MonoReflectionMethodBuilder*, j);
8596 event->other [j] = mb->mhandle;
8601 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
8602 if (!is_ok (error)) {
8603 #ifndef MONO_SMALL_CONFIG
8604 g_free (event->other);
8612 MonoReflectionEvent *
8613 ves_icall_TypeBuilder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8616 MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
8617 mono_error_set_pending_exception (&error);
8622 typebuilder_setup_events (MonoClass *klass, MonoError *error)
8624 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
8625 MonoReflectionEventBuilder *eb;
8626 MonoImage *image = klass->image;
8630 mono_error_init (error);
8633 klass->ext = image_g_new0 (image, MonoClassExt, 1);
8635 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
8636 klass->ext->event.first = 0;
8638 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
8639 klass->ext->events = events;
8640 for (i = 0; i < klass->ext->event.count; ++i) {
8641 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8642 events [i].parent = klass;
8643 events [i].attrs = eb->attrs;
8644 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
8645 if (!mono_error_ok (error))
8648 events [i].add = eb->add_method->mhandle;
8649 if (eb->remove_method)
8650 events [i].remove = eb->remove_method->mhandle;
8651 if (eb->raise_method)
8652 events [i].raise = eb->raise_method->mhandle;
8654 #ifndef MONO_SMALL_CONFIG
8655 if (eb->other_methods) {
8657 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
8658 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8659 MonoReflectionMethodBuilder *mb =
8660 mono_array_get (eb->other_methods,
8661 MonoReflectionMethodBuilder*, j);
8662 events [i].other [j] = mb->mhandle;
8666 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
8670 struct remove_instantiations_user_data
8677 remove_instantiations_of_and_ensure_contents (gpointer key,
8681 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
8682 MonoType *type = (MonoType*)key;
8683 MonoClass *klass = data->klass;
8684 gboolean already_failed = !is_ok (data->error);
8686 MonoError *error = already_failed ? &lerror : data->error;
8688 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
8689 MonoClass *inst_klass = mono_class_from_mono_type (type);
8690 //Ensure it's safe to use it.
8691 if (!fix_partial_generic_class (inst_klass, error)) {
8692 mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
8693 // Marked the class with failure, but since some other instantiation already failed,
8694 // just report that one, and swallow the error from this one.
8696 mono_error_cleanup (error);
8704 check_array_for_usertypes (MonoArray *arr, MonoError *error)
8706 mono_error_init (error);
8712 for (i = 0; i < mono_array_length (arr); ++i) {
8713 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
8714 if (!mono_error_ok (error))
8720 ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilder *tb)
8725 MonoReflectionType* res;
8728 mono_error_init (&error);
8730 domain = mono_object_domain (tb);
8731 klass = mono_class_from_mono_type (tb->type.type);
8734 * Check for user defined Type subclasses.
8736 RESOLVE_TYPE (tb->parent, &error);
8737 if (!is_ok (&error))
8738 goto failure_unlocked;
8739 check_array_for_usertypes (tb->interfaces, &error);
8740 if (!is_ok (&error))
8741 goto failure_unlocked;
8743 for (i = 0; i < mono_array_length (tb->fields); ++i) {
8744 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
8746 RESOLVE_TYPE (fb->type, &error);
8747 if (!is_ok (&error))
8748 goto failure_unlocked;
8749 check_array_for_usertypes (fb->modreq, &error);
8750 if (!is_ok (&error))
8751 goto failure_unlocked;
8752 check_array_for_usertypes (fb->modopt, &error);
8753 if (!is_ok (&error))
8754 goto failure_unlocked;
8755 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
8756 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
8757 if (!is_ok (&error))
8758 goto failure_unlocked;
8764 for (i = 0; i < mono_array_length (tb->methods); ++i) {
8765 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
8767 RESOLVE_TYPE (mb->rtype, &error);
8768 if (!is_ok (&error))
8769 goto failure_unlocked;
8770 check_array_for_usertypes (mb->return_modreq, &error);
8771 if (!is_ok (&error))
8772 goto failure_unlocked;
8773 check_array_for_usertypes (mb->return_modopt, &error);
8774 if (!is_ok (&error))
8775 goto failure_unlocked;
8776 check_array_for_usertypes (mb->parameters, &error);
8777 if (!is_ok (&error))
8778 goto failure_unlocked;
8779 if (mb->param_modreq)
8780 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
8781 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
8782 if (!is_ok (&error))
8783 goto failure_unlocked;
8785 if (mb->param_modopt)
8786 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
8787 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
8788 if (!is_ok (&error))
8789 goto failure_unlocked;
8795 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
8796 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
8798 check_array_for_usertypes (mb->parameters, &error);
8799 if (!is_ok (&error))
8800 goto failure_unlocked;
8801 if (mb->param_modreq)
8802 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
8803 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
8804 if (!is_ok (&error))
8805 goto failure_unlocked;
8807 if (mb->param_modopt)
8808 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
8809 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
8810 if (!is_ok (&error))
8811 goto failure_unlocked;
8817 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8820 * we need to lock the domain because the lock will be taken inside
8821 * So, we need to keep the locking order correct.
8823 mono_loader_lock ();
8824 mono_domain_lock (domain);
8825 if (klass->wastypebuilder) {
8826 mono_domain_unlock (domain);
8827 mono_loader_unlock ();
8829 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
8830 mono_error_set_pending_exception (&error);
8835 * Fields to set in klass:
8836 * the various flags: delegate/unicode/contextbound etc.
8838 klass->flags = tb->attrs;
8839 klass->has_cctor = 1;
8841 mono_class_setup_parent (klass, klass->parent);
8842 /* fool mono_class_setup_supertypes */
8843 klass->supertypes = NULL;
8844 mono_class_setup_supertypes (klass);
8845 mono_class_setup_mono_type (klass);
8848 if (!((MonoDynamicImage*)klass->image)->run) {
8849 if (klass->generic_container) {
8850 /* FIXME: The code below can't handle generic classes */
8851 klass->wastypebuilder = TRUE;
8852 mono_loader_unlock ();
8853 mono_domain_unlock (domain);
8855 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
8856 mono_error_set_pending_exception (&error);
8863 /* enums are done right away */
8864 if (!klass->enumtype)
8865 if (!ensure_runtime_vtable (klass, &error))
8869 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8870 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8871 mono_class_alloc_ext (klass);
8872 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
8873 if (!is_ok (&error)) goto failure;
8874 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
8878 klass->nested_classes_inited = TRUE;
8880 /* fields and object layout */
8881 if (klass->parent) {
8882 if (!klass->parent->size_inited)
8883 mono_class_init (klass->parent);
8884 klass->instance_size = klass->parent->instance_size;
8885 klass->sizes.class_size = 0;
8886 klass->min_align = klass->parent->min_align;
8887 /* if the type has no fields we won't call the field_setup
8888 * routine which sets up klass->has_references.
8890 klass->has_references |= klass->parent->has_references;
8892 klass->instance_size = sizeof (MonoObject);
8893 klass->min_align = 1;
8896 /* FIXME: handle packing_size and instance_size */
8897 typebuilder_setup_fields (klass, &error);
8898 if (!mono_error_ok (&error))
8900 typebuilder_setup_properties (klass, &error);
8901 if (!mono_error_ok (&error))
8904 typebuilder_setup_events (klass, &error);
8905 if (!mono_error_ok (&error))
8908 klass->wastypebuilder = TRUE;
8911 * If we are a generic TypeBuilder, there might be instantiations in the type cache
8912 * which have type System.Reflection.MonoGenericClass, but after the type is created,
8913 * we want to return normal System.MonoType objects, so clear these out from the cache.
8915 * Together with this we must ensure the contents of all instances to match the created type.
8917 if (domain->type_hash && klass->generic_container) {
8918 struct remove_instantiations_user_data data;
8920 data.error = &error;
8921 mono_error_assert_ok (&error);
8922 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
8923 if (!is_ok (&error))
8927 mono_domain_unlock (domain);
8928 mono_loader_unlock ();
8930 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
8931 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
8932 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
8933 goto failure_unlocked;
8936 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
8937 if (!is_ok (&error))
8938 goto failure_unlocked;
8940 g_assert (res != (MonoReflectionType*)tb);
8945 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
8946 klass->wastypebuilder = TRUE;
8947 mono_domain_unlock (domain);
8948 mono_loader_unlock ();
8950 mono_error_set_pending_exception (&error);
8955 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
8957 MonoGenericParamFull *param;
8961 mono_error_init (error);
8963 image = &gparam->tbuilder->module->dynamic_image->image;
8965 param = mono_image_new0 (image, MonoGenericParamFull, 1);
8967 param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
8968 mono_error_assert_ok (error);
8969 param->param.num = gparam->index;
8971 if (gparam->mbuilder) {
8972 if (!gparam->mbuilder->generic_container) {
8973 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
8974 return_val_if_nok (error, FALSE);
8976 MonoClass *klass = mono_class_from_mono_type (tb);
8977 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
8978 gparam->mbuilder->generic_container->is_method = TRUE;
8980 * Cannot set owner.method, since the MonoMethod is not created yet.
8981 * Set the image field instead, so type_in_image () works.
8983 gparam->mbuilder->generic_container->is_anonymous = TRUE;
8984 gparam->mbuilder->generic_container->owner.image = klass->image;
8986 param->param.owner = gparam->mbuilder->generic_container;
8987 } else if (gparam->tbuilder) {
8988 if (!gparam->tbuilder->generic_container) {
8989 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
8990 return_val_if_nok (error, FALSE);
8991 MonoClass *klass = mono_class_from_mono_type (tb);
8992 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
8993 gparam->tbuilder->generic_container->owner.klass = klass;
8995 param->param.owner = gparam->tbuilder->generic_container;
8998 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
9000 gparam->type.type = &pklass->byval_arg;
9002 mono_class_set_ref_info (pklass, gparam);
9003 mono_image_append_class_to_reflection_info_set (pklass);
9009 ves_icall_GenericTypeParameterBuilder_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9012 (void) reflection_initialize_generic_parameter (gparam, &error);
9013 mono_error_set_pending_exception (&error);
9018 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
9020 MonoReflectionModuleBuilder *module = sig->module;
9021 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
9022 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
9027 mono_error_init (error);
9029 check_array_for_usertypes (sig->arguments, error);
9030 return_val_if_nok (error, NULL);
9032 sigbuffer_init (&buf, 32);
9034 sigbuffer_add_value (&buf, 0x07);
9035 sigbuffer_add_value (&buf, na);
9036 if (assembly != NULL){
9037 for (i = 0; i < na; ++i) {
9038 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
9039 encode_reflection_type (assembly, type, &buf, error);
9040 if (!is_ok (error)) goto fail;
9044 buflen = buf.p - buf.buf;
9045 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
9046 if (!is_ok (error)) goto fail;
9047 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9048 sigbuffer_free (&buf);
9051 sigbuffer_free (&buf);
9056 ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig)
9059 MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
9060 mono_error_set_pending_exception (&error);
9065 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
9067 MonoDynamicImage *assembly = sig->module->dynamic_image;
9068 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
9073 mono_error_init (error);
9075 check_array_for_usertypes (sig->arguments, error);
9076 return_val_if_nok (error, NULL);
9078 sigbuffer_init (&buf, 32);
9080 sigbuffer_add_value (&buf, 0x06);
9081 for (i = 0; i < na; ++i) {
9082 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
9083 encode_reflection_type (assembly, type, &buf, error);
9088 buflen = buf.p - buf.buf;
9089 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
9090 if (!is_ok (error)) goto fail;
9091 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9092 sigbuffer_free (&buf);
9096 sigbuffer_free (&buf);
9101 ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig)
9104 MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
9105 mono_error_set_pending_exception (&error);
9112 } DynamicMethodReleaseData;
9115 * The runtime automatically clean up those after finalization.
9117 static MonoReferenceQueue *dynamic_method_queue;
9120 free_dynamic_method (void *dynamic_method)
9122 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
9123 MonoDomain *domain = data->domain;
9124 MonoMethod *method = data->handle;
9127 mono_domain_lock (domain);
9128 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
9129 g_hash_table_remove (domain->method_to_dyn_method, method);
9130 mono_domain_unlock (domain);
9131 g_assert (dis_link);
9132 mono_gchandle_free (dis_link);
9134 mono_runtime_free_method (domain, method);
9139 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
9141 MonoReferenceQueue *queue;
9143 DynamicMethodReleaseData *release_data;
9144 ReflectionMethodBuilder rmb;
9145 MonoMethodSignature *sig;
9151 mono_error_init (error);
9153 if (mono_runtime_is_shutting_down ()) {
9154 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
9158 if (!(queue = dynamic_method_queue)) {
9159 mono_loader_lock ();
9160 if (!(queue = dynamic_method_queue))
9161 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
9162 mono_loader_unlock ();
9165 sig = dynamic_method_to_signature (mb, error);
9166 return_val_if_nok (error, FALSE);
9168 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9171 * Resolve references.
9174 * Every second entry in the refs array is reserved for storing handle_class,
9175 * which is needed by the ldtoken implementation in the JIT.
9177 rmb.nrefs = mb->nrefs;
9178 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9179 for (i = 0; i < mb->nrefs; i += 2) {
9180 MonoClass *handle_class;
9182 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
9184 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9185 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9187 * The referenced DynamicMethod should already be created by the managed
9188 * code, except in the case of circular references. In that case, we store
9189 * method in the refs array, and fix it up later when the referenced
9190 * DynamicMethod is created.
9192 if (method->mhandle) {
9193 ref = method->mhandle;
9195 /* FIXME: GC object stored in unmanaged memory */
9198 /* FIXME: GC object stored in unmanaged memory */
9199 method->referenced_by = g_slist_append (method->referenced_by, mb);
9201 handle_class = mono_defaults.methodhandle_class;
9203 MonoException *ex = NULL;
9204 ref = mono_reflection_resolve_object (mb->module->image, obj, &handle_class, NULL, error);
9205 if (!is_ok (error)) {
9210 ex = mono_get_exception_type_load (NULL, NULL);
9211 else if (mono_security_core_clr_enabled ())
9212 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
9216 mono_error_set_exception_instance (error, ex);
9221 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9222 rmb.refs [i + 1] = handle_class;
9226 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
9227 if (!is_ok (error)) {
9231 klass = mono_class_from_mono_type (owner_type);
9233 klass = mono_defaults.object_class;
9236 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
9238 return_val_if_nok (error, FALSE);
9240 release_data = g_new (DynamicMethodReleaseData, 1);
9241 release_data->handle = handle;
9242 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
9243 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
9244 g_free (release_data);
9246 /* Fix up refs entries pointing at us */
9247 for (l = mb->referenced_by; l; l = l->next) {
9248 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
9249 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
9252 g_assert (method->mhandle);
9254 data = (gpointer*)wrapper->method_data;
9255 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
9256 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
9257 data [i + 1] = mb->mhandle;
9260 g_slist_free (mb->referenced_by);
9262 /* ilgen is no longer needed */
9265 domain = mono_domain_get ();
9266 mono_domain_lock (domain);
9267 if (!domain->method_to_dyn_method)
9268 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
9269 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
9270 mono_domain_unlock (domain);
9276 ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9279 (void) reflection_create_dynamic_method (mb, &error);
9280 mono_error_set_pending_exception (&error);
9283 #endif /* DISABLE_REFLECTION_EMIT */
9285 MonoMethodSignature *
9286 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
9288 MonoMethodSignature *sig;
9289 g_assert (image_is_dynamic (image));
9291 mono_error_init (error);
9293 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
9297 return mono_method_signature_checked (method, error);
9300 #ifndef DISABLE_REFLECTION_EMIT
9303 * ensure_complete_type:
9305 * Ensure that KLASS is completed if it is a dynamic type, or references
9309 ensure_complete_type (MonoClass *klass, MonoError *error)
9311 mono_error_init (error);
9313 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
9314 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
9316 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
9317 return_if_nok (error);
9319 // Asserting here could break a lot of code
9320 //g_assert (klass->wastypebuilder);
9323 if (klass->generic_class) {
9324 MonoGenericInst *inst = klass->generic_class->context.class_inst;
9327 for (i = 0; i < inst->type_argc; ++i) {
9328 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
9329 return_if_nok (error);
9335 mono_reflection_resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
9337 gpointer result = NULL;
9339 mono_error_init (error);
9341 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9342 result = mono_string_intern_checked ((MonoString*)obj, error);
9343 return_val_if_nok (error, NULL);
9344 *handle_class = mono_defaults.string_class;
9346 } else if (strcmp (obj->vtable->klass->name, "RuntimeType") == 0) {
9347 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
9348 return_val_if_nok (error, NULL);
9349 MonoClass *mc = mono_class_from_mono_type (type);
9350 if (!mono_class_init (mc)) {
9351 mono_error_set_for_class_failure (error, mc);
9356 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
9357 return_val_if_nok (error, NULL);
9359 result = mono_class_from_mono_type (inflated);
9360 mono_metadata_free_type (inflated);
9362 result = mono_class_from_mono_type (type);
9364 *handle_class = mono_defaults.typehandle_class;
9366 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9367 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9368 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9369 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9370 result = ((MonoReflectionMethod*)obj)->method;
9372 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
9373 mono_error_assert_ok (error);
9375 *handle_class = mono_defaults.methodhandle_class;
9377 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9378 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9379 result = mb->mhandle;
9381 /* Type is not yet created */
9382 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9384 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
9385 return_val_if_nok (error, NULL);
9388 * Hopefully this has been filled in by calling CreateType() on the
9392 * TODO: This won't work if the application finishes another
9393 * TypeBuilder instance instead of this one.
9395 result = mb->mhandle;
9398 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
9399 mono_error_assert_ok (error);
9401 *handle_class = mono_defaults.methodhandle_class;
9402 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9403 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9405 result = cb->mhandle;
9407 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9409 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
9410 return_val_if_nok (error, NULL);
9411 result = cb->mhandle;
9414 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
9415 mono_error_assert_ok (error);
9417 *handle_class = mono_defaults.methodhandle_class;
9418 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9419 MonoClassField *field = ((MonoReflectionField*)obj)->field;
9421 ensure_complete_type (field->parent, error);
9422 return_val_if_nok (error, NULL);
9425 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
9426 return_val_if_nok (error, NULL);
9428 MonoClass *klass = mono_class_from_mono_type (inflated);
9429 MonoClassField *inflated_field;
9430 gpointer iter = NULL;
9431 mono_metadata_free_type (inflated);
9432 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
9433 if (!strcmp (field->name, inflated_field->name))
9436 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
9437 result = inflated_field;
9441 *handle_class = mono_defaults.fieldhandle_class;
9443 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9444 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9445 result = fb->handle;
9448 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9450 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
9451 return_val_if_nok (error, NULL);
9452 result = fb->handle;
9455 if (fb->handle && fb->handle->parent->generic_container) {
9456 MonoClass *klass = fb->handle->parent;
9457 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
9458 return_val_if_nok (error, NULL);
9460 MonoClass *inflated = mono_class_from_mono_type (type);
9462 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
9464 mono_metadata_free_type (type);
9466 *handle_class = mono_defaults.fieldhandle_class;
9467 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9468 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9469 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
9470 return_val_if_nok (error, NULL);
9473 klass = type->data.klass;
9474 if (klass->wastypebuilder) {
9475 /* Already created */
9479 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
9480 return_val_if_nok (error, NULL);
9481 result = type->data.klass;
9484 *handle_class = mono_defaults.typehandle_class;
9485 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9486 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9487 MonoMethodSignature *sig;
9490 if (helper->arguments)
9491 nargs = mono_array_length (helper->arguments);
9495 sig = mono_metadata_signature_alloc (image, nargs);
9496 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9497 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9499 if (helper->unmanaged_call_conv) { /* unmanaged */
9500 sig->call_convention = helper->unmanaged_call_conv - 1;
9501 sig->pinvoke = TRUE;
9502 } else if (helper->call_conv & 0x02) {
9503 sig->call_convention = MONO_CALL_VARARG;
9505 sig->call_convention = MONO_CALL_DEFAULT;
9508 sig->param_count = nargs;
9509 /* TODO: Copy type ? */
9510 sig->ret = helper->return_type->type;
9511 for (i = 0; i < nargs; ++i) {
9512 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
9513 if (!is_ok (error)) {
9514 image_g_free (image, sig);
9520 *handle_class = NULL;
9521 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9522 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9523 /* Already created by the managed code */
9524 g_assert (method->mhandle);
9525 result = method->mhandle;
9526 *handle_class = mono_defaults.methodhandle_class;
9527 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
9528 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
9529 return_val_if_nok (error, NULL);
9530 type = mono_class_inflate_generic_type_checked (type, context, error);
9531 return_val_if_nok (error, NULL);
9533 result = mono_class_from_mono_type (type);
9534 *handle_class = mono_defaults.typehandle_class;
9536 mono_metadata_free_type (type);
9537 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
9538 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
9539 return_val_if_nok (error, NULL);
9540 type = mono_class_inflate_generic_type_checked (type, context, error);
9541 return_val_if_nok (error, NULL);
9543 result = mono_class_from_mono_type (type);
9544 *handle_class = mono_defaults.typehandle_class;
9546 mono_metadata_free_type (type);
9547 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
9548 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
9549 MonoClass *inflated;
9551 MonoClassField *field;
9553 if (is_sre_field_builder (mono_object_class (f->fb)))
9554 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
9555 else if (is_sr_mono_field (mono_object_class (f->fb)))
9556 field = ((MonoReflectionField*)f->fb)->field;
9558 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)));
9560 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
9561 return_val_if_nok (error, NULL);
9562 type = mono_class_inflate_generic_type_checked (finst, context, error);
9563 return_val_if_nok (error, NULL);
9565 inflated = mono_class_from_mono_type (type);
9567 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
9568 ensure_complete_type (field->parent, error);
9569 if (!is_ok (error)) {
9570 mono_metadata_free_type (type);
9575 mono_metadata_free_type (type);
9576 *handle_class = mono_defaults.fieldhandle_class;
9577 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
9578 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
9579 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
9580 return_val_if_nok (error, NULL);
9581 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
9582 return_val_if_nok (error, NULL);
9584 MonoClass *inflated_klass = mono_class_from_mono_type (type);
9587 if (mono_is_sre_ctor_builder (mono_object_class (c->cb)))
9588 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9589 else if (mono_is_sr_mono_cmethod (mono_object_class (c->cb)))
9590 method = ((MonoReflectionMethod *)c->cb)->method;
9592 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)));
9594 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
9595 *handle_class = mono_defaults.methodhandle_class;
9596 mono_metadata_free_type (type);
9597 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
9598 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
9599 if (m->method_args) {
9600 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
9601 return_val_if_nok (error, NULL);
9603 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
9604 mono_error_assert_ok (error);
9607 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
9608 return_val_if_nok (error, NULL);
9609 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
9610 return_val_if_nok (error, NULL);
9612 MonoClass *inflated_klass = mono_class_from_mono_type (type);
9615 if (is_sre_method_builder (mono_object_class (m->mb)))
9616 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
9617 else if (is_sr_mono_method (mono_object_class (m->mb)))
9618 method = ((MonoReflectionMethod *)m->mb)->method;
9620 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)));
9622 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
9623 mono_metadata_free_type (type);
9625 *handle_class = mono_defaults.methodhandle_class;
9626 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
9627 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
9634 mtype = mono_reflection_type_get_handle (m->parent, error);
9635 return_val_if_nok (error, NULL);
9636 klass = mono_class_from_mono_type (mtype);
9638 /* Find the method */
9640 name = mono_string_to_utf8_checked (m->name, error);
9641 return_val_if_nok (error, NULL);
9643 while ((method = mono_class_get_methods (klass, &iter))) {
9644 if (!strcmp (method->name, name))
9651 // FIXME: Check parameters/return value etc. match
9654 *handle_class = mono_defaults.methodhandle_class;
9655 } else if (is_sre_array (mono_object_get_class(obj)) ||
9656 is_sre_byref (mono_object_get_class(obj)) ||
9657 is_sre_pointer (mono_object_get_class(obj))) {
9658 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
9659 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
9660 return_val_if_nok (error, NULL);
9663 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
9664 return_val_if_nok (error, NULL);
9666 result = mono_class_from_mono_type (inflated);
9667 mono_metadata_free_type (inflated);
9669 result = mono_class_from_mono_type (type);
9671 *handle_class = mono_defaults.typehandle_class;
9673 g_print ("%s\n", obj->vtable->klass->name);
9674 g_assert_not_reached ();
9679 #else /* DISABLE_REFLECTION_EMIT */
9682 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9684 g_assert_not_reached ();
9689 ves_icall_TypeBuilder_setup_internal_class (MonoReflectionTypeBuilder *tb)
9691 g_assert_not_reached ();
9695 ves_icall_TypeBuilder_setup_generic_class (MonoReflectionTypeBuilder *tb)
9697 g_assert_not_reached ();
9701 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
9703 g_assert_not_reached ();
9708 ves_icall_TypeBuilder_create_internal_class (MonoReflectionTypeBuilder *tb)
9710 g_assert_not_reached ();
9714 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
9716 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
9720 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
9722 g_assert_not_reached ();
9725 MonoReflectionModule *
9726 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
9728 g_assert_not_reached ();
9733 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
9735 g_assert_not_reached ();
9740 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
9742 g_assert_not_reached ();
9747 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
9748 gboolean create_open_instance, gboolean register_token, MonoError *error)
9750 g_assert_not_reached ();
9755 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
9757 g_assert_not_reached ();
9761 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
9763 mono_error_init (error);
9768 MonoReflectionEvent *
9769 ves_icall_TypeBuilder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9771 g_assert_not_reached ();
9776 ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilder *tb)
9778 g_assert_not_reached ();
9783 ves_icall_GenericTypeParameterBuilder_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9785 g_assert_not_reached ();
9789 ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig)
9791 g_assert_not_reached ();
9796 ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig)
9798 g_assert_not_reached ();
9803 ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9808 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
9810 mono_error_init (error);
9817 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
9819 g_assert_not_reached ();
9822 #endif /* DISABLE_REFLECTION_EMIT */
9824 #ifndef DISABLE_REFLECTION_EMIT
9826 mono_reflection_method_builder_to_mono_method (MonoReflectionMethodBuilder *mb, MonoError *error)
9831 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
9832 return_val_if_nok (error, NULL);
9833 klass = mono_class_from_mono_type (tb);
9835 return methodbuilder_to_mono_method (klass, mb, error);
9837 #else /* DISABLE_REFLECTION_EMIT */
9839 mono_reflection_method_builder_to_mono_method (MonoReflectionMethodBuilder *mb, MonoError *error)
9841 g_assert_not_reached ();
9844 #endif /* DISABLE_REFLECTION_EMIT */
9847 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
9849 MONO_CHECK_ARG_NULL (obj, 0);
9852 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
9853 mono_error_set_pending_exception (&error);
9858 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
9859 MonoReflectionMethod *method,
9860 MonoArray *opt_param_types)
9862 MONO_CHECK_ARG_NULL (method, 0);
9865 gint32 result = mono_image_create_method_token (
9866 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
9867 mono_error_set_pending_exception (&error);
9872 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
9875 mono_image_create_pefile (mb, file, &error);
9876 mono_error_set_pending_exception (&error);
9880 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
9883 mono_image_build_metadata (mb, &error);
9884 mono_error_set_pending_exception (&error);
9888 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
9890 mono_image_register_token (mb->dynamic_image, token, obj);
9894 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
9898 mono_loader_lock ();
9899 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
9900 mono_loader_unlock ();
9905 MonoReflectionModule*
9906 ves_icall_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
9909 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
9910 mono_error_set_pending_exception (&error);
9915 * ves_icall_TypeBuilder_create_generic_class:
9916 * @tb: a TypeBuilder object
9919 * Creates the generic class after all generic parameters have been added.
9922 ves_icall_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
9925 (void) mono_reflection_create_generic_class (tb, &error);
9926 mono_error_set_pending_exception (&error);
9929 #ifndef DISABLE_REFLECTION_EMIT
9931 ves_icall_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9934 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
9935 mono_error_set_pending_exception (&error);
9941 ves_icall_AssemblyBuilder_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
9943 mono_image_basic_init (assemblyb);
9947 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
9949 return mono_type_is_generic_parameter (tb->type.type);
9953 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
9954 MonoReflectionType *t)
9956 enumtype->type = t->type;
9960 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
9963 MonoReflectionType *ret;
9965 int isbyref = 0, rank;
9967 char *str = mono_string_to_utf8_checked (smodifiers, &error);
9968 if (mono_error_set_pending_exception (&error))
9971 klass = mono_class_from_mono_type (tb->type.type);
9973 /* logic taken from mono_reflection_parse_type(): keep in sync */
9977 if (isbyref) { /* only one level allowed by the spec */
9986 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
9987 mono_error_set_pending_exception (&error);
9991 klass = mono_ptr_class_get (&klass->byval_arg);
9992 mono_class_init (klass);
10003 else if (*p != '*') { /* '*' means unknown lower bound */
10014 klass = mono_array_class_get (klass, rank);
10015 mono_class_init (klass);
10024 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
10025 mono_error_set_pending_exception (&error);
10031 ves_icall_ModuleBuilder_basic_init (MonoReflectionModuleBuilder *moduleb)
10033 mono_image_module_basic_init (moduleb);
10037 ves_icall_ModuleBuilder_getUSIndex (MonoReflectionModuleBuilder *module, MonoString *str)
10039 return mono_image_insert_string (module, str);
10043 ves_icall_ModuleBuilder_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
10045 MonoDynamicImage *image = moduleb->dynamic_image;
10047 g_assert (type->type);
10048 image->wrappers_type = mono_class_from_mono_type (type->type);