2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/utils/mono-membar.h"
13 #include "mono/metadata/reflection.h"
14 #include "mono/metadata/tabledefs.h"
15 #include "mono/metadata/metadata-internals.h"
16 #include <mono/metadata/profiler-private.h>
17 #include "mono/metadata/class-internals.h"
18 #include "mono/metadata/gc-internal.h"
19 #include "mono/metadata/tokentype.h"
20 #include "mono/metadata/domain-internals.h"
21 #include "mono/metadata/opcodes.h"
22 #include "mono/metadata/assembly.h"
23 #include "mono/metadata/object-internals.h"
24 #include <mono/metadata/exception.h>
25 #include <mono/metadata/marshal.h>
26 #include <mono/metadata/security-manager.h>
35 #include "mono-endian.h"
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/mempool-internals.h>
40 static void* reflection_info_desc = NULL;
41 #define MOVING_GC_REGISTER(addr) do { \
42 if (!reflection_info_desc) { \
44 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
46 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
49 #define MOVING_GC_REGISTER(addr)
58 #define TEXT_OFFSET 512
59 #define CLI_H_SIZE 136
60 #define FILE_ALIGN 512
61 #define VIRT_ALIGN 8192
62 #define START_TEXT_RVA 0x00002000
65 MonoReflectionILGen *ilgen;
66 MonoReflectionType *rtype;
67 MonoArray *parameters;
68 MonoArray *generic_params;
69 MonoGenericContainer *generic_container;
75 guint32 *table_idx; /* note: it's a pointer */
79 MonoBoolean init_locals;
80 MonoBoolean skip_visibility;
81 MonoArray *return_modreq;
82 MonoArray *return_modopt;
83 MonoArray *param_modreq;
84 MonoArray *param_modopt;
85 MonoArray *permissions;
90 int charset, extra_flags, native_cc;
91 MonoString *dll, *dllentry;
92 } ReflectionMethodBuilder;
96 MonoReflectionGenericParam *gparam;
97 } GenericParamTableEntry;
99 const unsigned char table_sizes [MONO_TABLE_NUM] = {
109 MONO_INTERFACEIMPL_SIZE,
110 MONO_MEMBERREF_SIZE, /* 0x0A */
112 MONO_CUSTOM_ATTR_SIZE,
113 MONO_FIELD_MARSHAL_SIZE,
114 MONO_DECL_SECURITY_SIZE,
115 MONO_CLASS_LAYOUT_SIZE,
116 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
117 MONO_STAND_ALONE_SIGNATURE_SIZE,
121 MONO_PROPERTY_MAP_SIZE,
124 MONO_METHOD_SEMA_SIZE,
125 MONO_METHODIMPL_SIZE,
126 MONO_MODULEREF_SIZE, /* 0x1A */
132 MONO_ASSEMBLY_SIZE, /* 0x20 */
133 MONO_ASSEMBLY_PROCESSOR_SIZE,
134 MONO_ASSEMBLYOS_SIZE,
135 MONO_ASSEMBLYREF_SIZE,
136 MONO_ASSEMBLYREFPROC_SIZE,
137 MONO_ASSEMBLYREFOS_SIZE,
141 MONO_NESTED_CLASS_SIZE,
143 MONO_GENERICPARAM_SIZE, /* 0x2A */
144 MONO_METHODSPEC_SIZE,
145 MONO_GENPARCONSTRAINT_SIZE
149 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
150 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
151 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
152 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
153 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
154 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
155 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
156 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
157 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
158 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
159 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
160 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
161 static void ensure_runtime_vtable (MonoClass *klass);
162 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
163 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
164 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
165 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
166 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
167 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
168 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
169 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
171 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
172 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
173 static CRITICAL_SECTION reflection_mutex;
176 mono_reflection_init (void)
178 InitializeCriticalSection (&reflection_mutex);
182 sigbuffer_init (SigBuffer *buf, int size)
184 buf->buf = g_malloc (size);
186 buf->end = buf->buf + size;
190 sigbuffer_make_room (SigBuffer *buf, int size)
192 if (buf->end - buf->p < size) {
193 int new_size = buf->end - buf->buf + size + 32;
194 char *p = g_realloc (buf->buf, new_size);
195 size = buf->p - buf->buf;
198 buf->end = buf->buf + new_size;
203 sigbuffer_add_value (SigBuffer *buf, guint32 val)
205 sigbuffer_make_room (buf, 6);
206 mono_metadata_encode_value (val, buf->p, &buf->p);
210 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
212 sigbuffer_make_room (buf, 1);
218 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
220 sigbuffer_make_room (buf, size);
221 memcpy (buf->p, p, size);
226 sigbuffer_free (SigBuffer *buf)
234 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
238 mp_g_malloc (MonoMemPool *mp, guint size)
241 return mono_mempool_alloc (mp, size);
243 return g_malloc (size);
249 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
253 mp_g_malloc0 (MonoMemPool *mp, guint size)
256 return mono_mempool_alloc0 (mp, size);
258 return g_malloc0 (size);
264 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
265 * memory from the C heap.
268 mp_string_to_utf8 (MonoMemPool *mp, MonoString *s)
271 return mono_string_to_utf8_mp (mp, s);
273 return mono_string_to_utf8 (s);
276 #define mp_g_new(mp,struct_type, n_structs) \
277 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
279 #define mp_g_new0(mp,struct_type, n_structs) \
280 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
283 alloc_table (MonoDynamicTable *table, guint nrows)
286 g_assert (table->columns);
287 if (nrows + 1 >= table->alloc_rows) {
288 while (nrows + 1 >= table->alloc_rows) {
289 if (table->alloc_rows == 0)
290 table->alloc_rows = 16;
292 table->alloc_rows *= 2;
295 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
300 make_room_in_stream (MonoDynamicStream *stream, int size)
302 if (size <= stream->alloc_size)
305 while (stream->alloc_size <= size) {
306 if (stream->alloc_size < 4096)
307 stream->alloc_size = 4096;
309 stream->alloc_size *= 2;
312 stream->data = g_realloc (stream->data, stream->alloc_size);
316 string_heap_insert (MonoDynamicStream *sh, const char *str)
320 gpointer oldkey, oldval;
322 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
323 return GPOINTER_TO_UINT (oldval);
325 len = strlen (str) + 1;
328 make_room_in_stream (sh, idx + len);
331 * We strdup the string even if we already copy them in sh->data
332 * so that the string pointers in the hash remain valid even if
333 * we need to realloc sh->data. We may want to avoid that later.
335 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
336 memcpy (sh->data + idx, str, len);
342 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
344 char *name = mono_string_to_utf8 (str);
346 idx = string_heap_insert (sh, name);
352 string_heap_init (MonoDynamicStream *sh)
355 sh->alloc_size = 4096;
356 sh->data = g_malloc (4096);
357 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
358 string_heap_insert (sh, "");
362 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
366 make_room_in_stream (stream, stream->index + len);
367 memcpy (stream->data + stream->index, data, len);
369 stream->index += len;
371 * align index? Not without adding an additional param that controls it since
372 * we may store a blob value in pieces.
378 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
382 make_room_in_stream (stream, stream->index + len);
383 memset (stream->data + stream->index, 0, len);
385 stream->index += len;
390 stream_data_align (MonoDynamicStream *stream)
393 guint32 count = stream->index % 4;
395 /* we assume the stream data will be aligned */
397 mono_image_add_stream_data (stream, buf, 4 - count);
401 mono_blob_entry_hash (const char* str)
405 len = mono_metadata_decode_blob_size (str, &str);
409 for (str += 1; str < end; str++)
410 h = (h << 5) - h + *str;
418 mono_blob_entry_equal (const char *str1, const char *str2) {
422 len = mono_metadata_decode_blob_size (str1, &end1);
423 len2 = mono_metadata_decode_blob_size (str2, &end2);
426 return memcmp (end1, end2, len) == 0;
430 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
434 gpointer oldkey, oldval;
436 copy = g_malloc (s1+s2);
437 memcpy (copy, b1, s1);
438 memcpy (copy + s1, b2, s2);
439 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
441 idx = GPOINTER_TO_UINT (oldval);
443 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
444 mono_image_add_stream_data (&assembly->blob, b2, s2);
445 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
451 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
455 guint32 size = buf->p - buf->buf;
457 g_assert (size <= (buf->end - buf->buf));
458 mono_metadata_encode_value (size, b, &b);
459 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
463 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
464 * dest may be misaligned.
467 swap_with_size (char *dest, const char* val, int len, int nelem) {
468 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
471 for (elem = 0; elem < nelem; ++elem) {
497 g_assert_not_reached ();
503 memcpy (dest, val, len * nelem);
508 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
512 guint32 idx = 0, len;
514 len = str->length * 2;
515 mono_metadata_encode_value (len, b, &b);
516 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
518 char *swapped = g_malloc (2 * mono_string_length (str));
519 const char *p = (const char*)mono_string_chars (str);
521 swap_with_size (swapped, p, 2, mono_string_length (str));
522 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
526 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
531 /* modified version needed to handle building corlib */
533 my_mono_class_from_mono_type (MonoType *type) {
534 switch (type->type) {
535 case MONO_TYPE_ARRAY:
537 case MONO_TYPE_SZARRAY:
538 case MONO_TYPE_GENERICINST:
539 return mono_class_from_mono_type (type);
542 g_assert (type->data.generic_param->pklass);
543 return type->data.generic_param->pklass;
545 /* should be always valid when we reach this case... */
546 return type->data.klass;
551 default_class_from_mono_type (MonoType *type)
553 switch (type->type) {
554 case MONO_TYPE_OBJECT:
555 return mono_defaults.object_class;
557 return mono_defaults.void_class;
558 case MONO_TYPE_BOOLEAN:
559 return mono_defaults.boolean_class;
561 return mono_defaults.char_class;
563 return mono_defaults.sbyte_class;
565 return mono_defaults.byte_class;
567 return mono_defaults.int16_class;
569 return mono_defaults.uint16_class;
571 return mono_defaults.int32_class;
573 return mono_defaults.uint32_class;
575 return mono_defaults.int_class;
577 return mono_defaults.uint_class;
579 return mono_defaults.int64_class;
581 return mono_defaults.uint64_class;
583 return mono_defaults.single_class;
585 return mono_defaults.double_class;
586 case MONO_TYPE_STRING:
587 return mono_defaults.string_class;
589 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
590 g_assert_not_reached ();
597 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
600 MonoGenericInst *class_inst;
605 class_inst = gclass->context.class_inst;
607 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
608 klass = gclass->container_class;
609 sigbuffer_add_value (buf, klass->byval_arg.type);
610 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
612 sigbuffer_add_value (buf, class_inst->type_argc);
613 for (i = 0; i < class_inst->type_argc; ++i)
614 encode_type (assembly, class_inst->type_argv [i], buf);
619 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
622 g_assert_not_reached ();
627 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
631 case MONO_TYPE_BOOLEAN:
645 case MONO_TYPE_STRING:
646 case MONO_TYPE_OBJECT:
647 case MONO_TYPE_TYPEDBYREF:
648 sigbuffer_add_value (buf, type->type);
651 sigbuffer_add_value (buf, type->type);
652 encode_type (assembly, type->data.type, buf);
654 case MONO_TYPE_SZARRAY:
655 sigbuffer_add_value (buf, type->type);
656 encode_type (assembly, &type->data.klass->byval_arg, buf);
658 case MONO_TYPE_VALUETYPE:
659 case MONO_TYPE_CLASS: {
660 MonoClass *k = mono_class_from_mono_type (type);
662 if (k->generic_container) {
663 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
664 encode_generic_class (assembly, gclass, buf);
667 * Make sure we use the correct type.
669 sigbuffer_add_value (buf, k->byval_arg.type);
671 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
672 * otherwise two typerefs could point to the same type, leading to
673 * verification errors.
675 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
679 case MONO_TYPE_ARRAY:
680 sigbuffer_add_value (buf, type->type);
681 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
682 sigbuffer_add_value (buf, type->data.array->rank);
683 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
684 sigbuffer_add_value (buf, 0);
686 case MONO_TYPE_GENERICINST:
687 encode_generic_class (assembly, type->data.generic_class, buf);
691 sigbuffer_add_value (buf, type->type);
692 sigbuffer_add_value (buf, type->data.generic_param->num);
695 g_error ("need to encode type %x", type->type);
700 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
703 sigbuffer_add_value (buf, MONO_TYPE_VOID);
708 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
709 encode_type (assembly, type->type, buf);
713 g_assert_not_reached ();
718 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
723 for (i = 0; i < mono_array_length (modreq); ++i) {
724 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
725 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
726 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
730 for (i = 0; i < mono_array_length (modopt); ++i) {
731 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
732 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
733 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
739 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
743 guint32 nparams = sig->param_count;
749 sigbuffer_init (&buf, 32);
751 * FIXME: vararg, explicit_this, differenc call_conv values...
753 idx = sig->call_convention;
755 idx |= 0x20; /* hasthis */
756 if (sig->generic_param_count)
757 idx |= 0x10; /* generic */
758 sigbuffer_add_byte (&buf, idx);
759 if (sig->generic_param_count)
760 sigbuffer_add_value (&buf, sig->generic_param_count);
761 sigbuffer_add_value (&buf, nparams);
762 encode_type (assembly, sig->ret, &buf);
763 for (i = 0; i < nparams; ++i) {
764 if (i == sig->sentinelpos)
765 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
766 encode_type (assembly, sig->params [i], &buf);
768 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
769 sigbuffer_free (&buf);
774 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
777 * FIXME: reuse code from method_encode_signature().
781 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
782 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
783 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
786 sigbuffer_init (&buf, 32);
787 /* LAMESPEC: all the call conv spec is foobared */
788 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
789 if (mb->call_conv & 2)
790 idx |= 0x5; /* vararg */
791 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
792 idx |= 0x20; /* hasthis */
794 idx |= 0x10; /* generic */
795 sigbuffer_add_byte (&buf, idx);
797 sigbuffer_add_value (&buf, ngparams);
798 sigbuffer_add_value (&buf, nparams + notypes);
799 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
800 encode_reflection_type (assembly, mb->rtype, &buf);
801 for (i = 0; i < nparams; ++i) {
802 MonoArray *modreq = NULL;
803 MonoArray *modopt = NULL;
804 MonoReflectionType *pt;
806 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
807 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
808 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
809 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
810 encode_custom_modifiers (assembly, modreq, modopt, &buf);
811 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
812 encode_reflection_type (assembly, pt, &buf);
815 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
816 for (i = 0; i < notypes; ++i) {
817 MonoReflectionType *pt;
819 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
820 encode_reflection_type (assembly, pt, &buf);
823 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
824 sigbuffer_free (&buf);
829 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
831 MonoDynamicTable *table;
833 guint32 idx, sig_idx;
834 guint nl = mono_array_length (ilgen->locals);
838 sigbuffer_init (&buf, 32);
839 sigbuffer_add_value (&buf, 0x07);
840 sigbuffer_add_value (&buf, nl);
841 for (i = 0; i < nl; ++i) {
842 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
845 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
847 encode_reflection_type (assembly, lb->type, &buf);
849 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
850 sigbuffer_free (&buf);
852 if (assembly->standalonesig_cache == NULL)
853 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
854 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
858 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
859 idx = table->next_idx ++;
861 alloc_table (table, table->rows);
862 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
864 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
866 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
872 method_count_clauses (MonoReflectionILGen *ilgen)
874 guint32 num_clauses = 0;
877 MonoILExceptionInfo *ex_info;
878 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
879 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
880 if (ex_info->handlers)
881 num_clauses += mono_array_length (ex_info->handlers);
889 static MonoExceptionClause*
890 method_encode_clauses (MonoMemPool *mp, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
892 MonoExceptionClause *clauses;
893 MonoExceptionClause *clause;
894 MonoILExceptionInfo *ex_info;
895 MonoILExceptionBlock *ex_block;
896 guint32 finally_start;
897 int i, j, clause_index;;
899 clauses = mp_g_new0 (mp, MonoExceptionClause, num_clauses);
902 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
903 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
904 finally_start = ex_info->start + ex_info->len;
905 if (!ex_info->handlers)
907 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
908 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
909 clause = &(clauses [clause_index]);
911 clause->flags = ex_block->type;
912 clause->try_offset = ex_info->start;
914 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
915 clause->try_len = finally_start - ex_info->start;
917 clause->try_len = ex_info->len;
918 clause->handler_offset = ex_block->start;
919 clause->handler_len = ex_block->len;
920 if (ex_block->extype) {
921 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
923 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
924 clause->data.filter_offset = ex_block->filter_offset;
926 clause->data.filter_offset = 0;
928 finally_start = ex_block->start + ex_block->len;
938 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
944 gint32 num_locals = 0;
945 gint32 num_exception = 0;
948 char fat_header [12];
951 guint32 local_sig = 0;
952 guint32 header_size = 12;
955 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
956 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
960 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
962 code = mb->ilgen->code;
963 code_size = mb->ilgen->code_len;
964 max_stack = mb->ilgen->max_stack;
965 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
966 if (mb->ilgen->ex_handlers)
967 num_exception = method_count_clauses (mb->ilgen);
971 char *name = mono_string_to_utf8 (mb->name);
972 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
973 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
976 mono_raise_exception (exception);
979 code_size = mono_array_length (code);
980 max_stack = 8; /* we probably need to run a verifier on the code... */
983 stream_data_align (&assembly->code);
985 /* check for exceptions, maxstack, locals */
986 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
988 if (code_size < 64 && !(code_size & 1)) {
989 flags = (code_size << 2) | 0x2;
990 } else if (code_size < 32 && (code_size & 1)) {
991 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
995 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
996 /* add to the fixup todo list */
997 if (mb->ilgen && mb->ilgen->num_token_fixups)
998 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
999 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1000 return assembly->text_rva + idx;
1004 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1006 * FIXME: need to set also the header size in fat_flags.
1007 * (and more sects and init locals flags)
1011 fat_flags |= METHOD_HEADER_MORE_SECTS;
1012 if (mb->init_locals)
1013 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1014 fat_header [0] = fat_flags;
1015 fat_header [1] = (header_size / 4 ) << 4;
1016 short_value = GUINT16_TO_LE (max_stack);
1017 memcpy (fat_header + 2, &short_value, 2);
1018 int_value = GUINT32_TO_LE (code_size);
1019 memcpy (fat_header + 4, &int_value, 4);
1020 int_value = GUINT32_TO_LE (local_sig);
1021 memcpy (fat_header + 8, &int_value, 4);
1022 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1023 /* add to the fixup todo list */
1024 if (mb->ilgen && mb->ilgen->num_token_fixups)
1025 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1027 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1028 if (num_exception) {
1029 unsigned char sheader [4];
1030 MonoILExceptionInfo * ex_info;
1031 MonoILExceptionBlock * ex_block;
1034 stream_data_align (&assembly->code);
1035 /* always use fat format for now */
1036 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1037 num_exception *= 6 * sizeof (guint32);
1038 num_exception += 4; /* include the size of the header */
1039 sheader [1] = num_exception & 0xff;
1040 sheader [2] = (num_exception >> 8) & 0xff;
1041 sheader [3] = (num_exception >> 16) & 0xff;
1042 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1043 /* fat header, so we are already aligned */
1045 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1046 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1047 if (ex_info->handlers) {
1048 int finally_start = ex_info->start + ex_info->len;
1049 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1051 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1053 val = GUINT32_TO_LE (ex_block->type);
1054 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1056 val = GUINT32_TO_LE (ex_info->start);
1057 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1058 /* need fault, too, probably */
1059 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1060 val = GUINT32_TO_LE (finally_start - ex_info->start);
1062 val = GUINT32_TO_LE (ex_info->len);
1063 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1064 /* handler offset */
1065 val = GUINT32_TO_LE (ex_block->start);
1066 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1068 val = GUINT32_TO_LE (ex_block->len);
1069 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1070 finally_start = ex_block->start + ex_block->len;
1071 if (ex_block->extype) {
1072 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1074 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1075 val = ex_block->filter_offset;
1079 val = GUINT32_TO_LE (val);
1080 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1081 /*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",
1082 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);*/
1085 g_error ("No clauses for ex info block %d", i);
1089 return assembly->text_rva + idx;
1093 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1096 MonoDynamicTable *table;
1099 table = &assembly->tables [table_idx];
1101 g_assert (col < table->columns);
1103 values = table->values + table->columns;
1104 for (i = 1; i <= table->rows; ++i) {
1105 if (values [col] == token)
1107 values += table->columns;
1113 * LOCKING: Acquires the loader lock.
1115 static MonoCustomAttrInfo*
1116 lookup_custom_attr (MonoImage *image, gpointer member)
1118 MonoCustomAttrInfo* res;
1120 mono_loader_lock ();
1121 res = mono_property_hash_lookup (image->property_hash, member, MONO_PROP_DYNAMIC_CATTR);
1122 mono_loader_unlock ();
1127 return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1131 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1133 /* FIXME: Need to do more checks */
1134 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1135 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1137 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1144 static MonoCustomAttrInfo*
1145 mono_custom_attrs_from_builders (MonoMemPool *mp, MonoImage *image, MonoArray *cattrs)
1147 int i, index, count, not_visible;
1148 MonoCustomAttrInfo *ainfo;
1149 MonoReflectionCustomAttr *cattr;
1153 /* FIXME: check in assembly the Run flag is set */
1155 count = mono_array_length (cattrs);
1157 /* Skip nonpublic attributes since MS.NET seems to do the same */
1158 /* FIXME: This needs to be done more globally */
1160 for (i = 0; i < count; ++i) {
1161 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1162 if (!custom_attr_visible (image, cattr))
1165 count -= not_visible;
1167 ainfo = mp_g_malloc0 (mp, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1169 ainfo->image = image;
1170 ainfo->num_attrs = count;
1171 ainfo->cached = mp != NULL;
1173 mono_loader_lock ();
1174 for (i = 0; i < count; ++i) {
1175 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1176 if (custom_attr_visible (image, cattr)) {
1177 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1178 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1179 ainfo->attrs [index].ctor = cattr->ctor->method;
1180 ainfo->attrs [index].data = saved;
1181 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1185 mono_loader_unlock ();
1191 * LOCKING: Acquires the loader lock.
1194 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1196 MonoCustomAttrInfo *ainfo, *tmp;
1198 if (!cattrs || !mono_array_length (cattrs))
1201 ainfo = mono_custom_attrs_from_builders (image->mempool, image, cattrs);
1202 mono_loader_lock ();
1203 tmp = mono_property_hash_lookup (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR);
1205 mono_custom_attrs_free (tmp);
1206 mono_property_hash_insert (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1207 mono_loader_unlock ();
1211 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1218 * idx is the table index of the object
1219 * type is one of MONO_CUSTOM_ATTR_*
1222 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1224 MonoDynamicTable *table;
1225 MonoReflectionCustomAttr *cattr;
1227 guint32 count, i, token;
1229 char *p = blob_size;
1231 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1234 count = mono_array_length (cattrs);
1235 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1236 table->rows += count;
1237 alloc_table (table, table->rows);
1238 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1239 idx <<= MONO_CUSTOM_ATTR_BITS;
1241 for (i = 0; i < count; ++i) {
1242 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1243 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1244 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1245 type = mono_metadata_token_index (token);
1246 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1247 switch (mono_metadata_token_table (token)) {
1248 case MONO_TABLE_METHOD:
1249 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1251 case MONO_TABLE_MEMBERREF:
1252 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1255 g_warning ("got wrong token in custom attr");
1258 values [MONO_CUSTOM_ATTR_TYPE] = type;
1260 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1261 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1262 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1263 values += MONO_CUSTOM_ATTR_SIZE;
1269 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1271 MonoDynamicTable *table;
1273 guint32 count, i, idx;
1274 MonoReflectionPermissionSet *perm;
1279 count = mono_array_length (permissions);
1280 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1281 table->rows += count;
1282 alloc_table (table, table->rows);
1284 for (i = 0; i < mono_array_length (permissions); ++i) {
1285 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1287 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1289 idx = mono_metadata_token_index (parent_token);
1290 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1291 switch (mono_metadata_token_table (parent_token)) {
1292 case MONO_TABLE_TYPEDEF:
1293 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1295 case MONO_TABLE_METHOD:
1296 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1298 case MONO_TABLE_ASSEMBLY:
1299 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1302 g_assert_not_reached ();
1305 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1306 values [MONO_DECL_SECURITY_PARENT] = idx;
1307 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1314 * Fill in the MethodDef and ParamDef tables for a method.
1315 * This is used for both normal methods and constructors.
1318 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1320 MonoDynamicTable *table;
1324 /* room in this table is already allocated */
1325 table = &assembly->tables [MONO_TABLE_METHOD];
1326 *mb->table_idx = table->next_idx ++;
1327 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1328 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1329 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1330 values [MONO_METHOD_FLAGS] = mb->attrs;
1331 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1332 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1333 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1335 table = &assembly->tables [MONO_TABLE_PARAM];
1336 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1338 mono_image_add_decl_security (assembly,
1339 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1342 MonoDynamicTable *mtable;
1345 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1346 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1349 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1350 if (mono_array_get (mb->pinfo, gpointer, i))
1353 table->rows += count;
1354 alloc_table (table, table->rows);
1355 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1356 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1357 MonoReflectionParamBuilder *pb;
1358 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1359 values [MONO_PARAM_FLAGS] = pb->attrs;
1360 values [MONO_PARAM_SEQUENCE] = i;
1361 if (pb->name != NULL) {
1362 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1364 values [MONO_PARAM_NAME] = 0;
1366 values += MONO_PARAM_SIZE;
1367 if (pb->marshal_info) {
1369 alloc_table (mtable, mtable->rows);
1370 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1371 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1372 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1374 pb->table_idx = table->next_idx++;
1375 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1376 guint32 field_type = 0;
1377 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1379 alloc_table (mtable, mtable->rows);
1380 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1381 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1382 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1383 mvalues [MONO_CONSTANT_TYPE] = field_type;
1384 mvalues [MONO_CONSTANT_PADDING] = 0;
1392 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1394 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1396 rmb->ilgen = mb->ilgen;
1397 rmb->rtype = mb->rtype;
1398 rmb->parameters = mb->parameters;
1399 rmb->generic_params = mb->generic_params;
1400 rmb->generic_container = mb->generic_container;
1401 rmb->opt_types = NULL;
1402 rmb->pinfo = mb->pinfo;
1403 rmb->attrs = mb->attrs;
1404 rmb->iattrs = mb->iattrs;
1405 rmb->call_conv = mb->call_conv;
1406 rmb->code = mb->code;
1407 rmb->type = mb->type;
1408 rmb->name = mb->name;
1409 rmb->table_idx = &mb->table_idx;
1410 rmb->init_locals = mb->init_locals;
1411 rmb->skip_visibility = FALSE;
1412 rmb->return_modreq = mb->return_modreq;
1413 rmb->return_modopt = mb->return_modopt;
1414 rmb->param_modreq = mb->param_modreq;
1415 rmb->param_modopt = mb->param_modopt;
1416 rmb->permissions = mb->permissions;
1417 rmb->mhandle = mb->mhandle;
1422 rmb->charset = mb->charset;
1423 rmb->extra_flags = mb->extra_flags;
1424 rmb->native_cc = mb->native_cc;
1425 rmb->dllentry = mb->dllentry;
1431 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1433 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1435 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1437 rmb->ilgen = mb->ilgen;
1438 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1439 rmb->parameters = mb->parameters;
1440 rmb->generic_params = NULL;
1441 rmb->generic_container = NULL;
1442 rmb->opt_types = NULL;
1443 rmb->pinfo = mb->pinfo;
1444 rmb->attrs = mb->attrs;
1445 rmb->iattrs = mb->iattrs;
1446 rmb->call_conv = mb->call_conv;
1448 rmb->type = mb->type;
1449 rmb->name = mono_string_new (mono_domain_get (), name);
1450 rmb->table_idx = &mb->table_idx;
1451 rmb->init_locals = mb->init_locals;
1452 rmb->skip_visibility = FALSE;
1453 rmb->return_modreq = NULL;
1454 rmb->return_modopt = NULL;
1455 rmb->param_modreq = mb->param_modreq;
1456 rmb->param_modopt = mb->param_modopt;
1457 rmb->permissions = mb->permissions;
1458 rmb->mhandle = mb->mhandle;
1464 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1466 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1468 rmb->ilgen = mb->ilgen;
1469 rmb->rtype = mb->rtype;
1470 rmb->parameters = mb->parameters;
1471 rmb->generic_params = NULL;
1472 rmb->generic_container = NULL;
1473 rmb->opt_types = NULL;
1475 rmb->attrs = mb->attrs;
1477 rmb->call_conv = mb->call_conv;
1479 rmb->type = (MonoObject *) mb->owner;
1480 rmb->name = mb->name;
1481 rmb->table_idx = NULL;
1482 rmb->init_locals = mb->init_locals;
1483 rmb->skip_visibility = mb->skip_visibility;
1484 rmb->return_modreq = NULL;
1485 rmb->return_modopt = NULL;
1486 rmb->param_modreq = NULL;
1487 rmb->param_modopt = NULL;
1488 rmb->permissions = NULL;
1489 rmb->mhandle = mb->mhandle;
1495 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1497 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1498 MonoDynamicTable *table;
1502 if (!mb->override_method)
1505 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1507 alloc_table (table, table->rows);
1508 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1509 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1510 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1512 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1513 switch (mono_metadata_token_table (tok)) {
1514 case MONO_TABLE_MEMBERREF:
1515 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1517 case MONO_TABLE_METHOD:
1518 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1521 g_assert_not_reached ();
1523 values [MONO_METHODIMPL_DECLARATION] = tok;
1527 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1529 MonoDynamicTable *table;
1531 ReflectionMethodBuilder rmb;
1534 reflection_methodbuilder_from_method_builder (&rmb, mb);
1536 mono_image_basic_method (&rmb, assembly);
1537 mb->table_idx = *rmb.table_idx;
1539 if (mb->dll) { /* It's a P/Invoke method */
1541 /* map CharSet values to on-disk values */
1542 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1543 int extra_flags = mb->extra_flags;
1544 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1546 alloc_table (table, table->rows);
1547 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1549 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1550 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1552 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1554 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1555 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1556 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1557 table = &assembly->tables [MONO_TABLE_MODULEREF];
1559 alloc_table (table, table->rows);
1560 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1561 values [MONO_IMPLMAP_SCOPE] = table->rows;
1565 if (mb->generic_params) {
1566 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1567 table->rows += mono_array_length (mb->generic_params);
1568 alloc_table (table, table->rows);
1569 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1570 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1572 mono_image_get_generic_param_info (
1573 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1580 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1582 ReflectionMethodBuilder rmb;
1584 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1586 mono_image_basic_method (&rmb, assembly);
1587 mb->table_idx = *rmb.table_idx;
1591 type_get_fully_qualified_name (MonoType *type)
1593 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1597 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1601 klass = my_mono_class_from_mono_type (type);
1603 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1604 ta = klass->image->assembly;
1605 if (ta->dynamic || (ta == ass)) {
1606 if (klass->generic_class || klass->generic_container)
1607 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1608 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1610 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1613 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1617 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1622 if (!assembly->save)
1625 sigbuffer_init (&buf, 32);
1627 sigbuffer_add_value (&buf, 0x06);
1628 /* encode custom attributes before the type */
1629 /* FIXME: This should probably go in encode_type () */
1630 if (type->num_mods) {
1631 for (i = 0; i < type->num_mods; ++i) {
1632 if (type->modifiers [i].required)
1633 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1635 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1636 sigbuffer_add_value (&buf, type->modifiers [i].token);
1639 encode_type (assembly, type, &buf);
1640 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1641 sigbuffer_free (&buf);
1646 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1651 sigbuffer_init (&buf, 32);
1653 sigbuffer_add_value (&buf, 0x06);
1654 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1655 /* encode custom attributes before the type */
1656 encode_reflection_type (assembly, fb->type, &buf);
1657 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1658 sigbuffer_free (&buf);
1663 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1664 char blob_size [64];
1665 char *b = blob_size;
1668 guint32 idx = 0, len = 0, dummy = 0;
1670 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1671 guint32 fpa_double [2];
1676 p = buf = g_malloc (64);
1678 *ret_type = MONO_TYPE_CLASS;
1680 box_val = (char*)&dummy;
1682 box_val = ((char*)val) + sizeof (MonoObject);
1683 *ret_type = val->vtable->klass->byval_arg.type;
1686 switch (*ret_type) {
1687 case MONO_TYPE_BOOLEAN:
1692 case MONO_TYPE_CHAR:
1709 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1710 fpa_p = (guint32*)box_val;
1711 fpa_double [0] = fpa_p [1];
1712 fpa_double [1] = fpa_p [0];
1713 box_val = (char*)fpa_double;
1717 case MONO_TYPE_VALUETYPE:
1718 if (val->vtable->klass->enumtype) {
1719 *ret_type = val->vtable->klass->enum_basetype->type;
1722 g_error ("we can't encode valuetypes");
1723 case MONO_TYPE_CLASS:
1725 case MONO_TYPE_STRING: {
1726 MonoString *str = (MonoString*)val;
1727 /* there is no signature */
1728 len = str->length * 2;
1729 mono_metadata_encode_value (len, b, &b);
1730 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1732 char *swapped = g_malloc (2 * mono_string_length (str));
1733 const char *p = (const char*)mono_string_chars (str);
1735 swap_with_size (swapped, p, 2, mono_string_length (str));
1736 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1740 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1746 case MONO_TYPE_GENERICINST:
1747 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1750 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1753 /* there is no signature */
1754 mono_metadata_encode_value (len, b, &b);
1755 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1756 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1757 swap_with_size (blob_size, box_val, len, 1);
1758 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1760 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1768 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1773 sigbuffer_init (&buf, 32);
1775 sigbuffer_add_value (&buf, minfo->type);
1777 switch (minfo->type) {
1778 case MONO_NATIVE_BYVALTSTR:
1779 case MONO_NATIVE_BYVALARRAY:
1780 sigbuffer_add_value (&buf, minfo->count);
1782 case MONO_NATIVE_LPARRAY:
1783 if (minfo->eltype || minfo->has_size) {
1784 sigbuffer_add_value (&buf, minfo->eltype);
1785 if (minfo->has_size) {
1786 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1787 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1789 /* LAMESPEC: ElemMult is undocumented */
1790 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1794 case MONO_NATIVE_CUSTOM:
1796 str = mono_string_to_utf8 (minfo->guid);
1798 sigbuffer_add_value (&buf, len);
1799 sigbuffer_add_mem (&buf, str, len);
1802 sigbuffer_add_value (&buf, 0);
1804 /* native type name */
1805 sigbuffer_add_value (&buf, 0);
1806 /* custom marshaler type name */
1807 if (minfo->marshaltype || minfo->marshaltyperef) {
1808 if (minfo->marshaltyperef)
1809 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1811 str = mono_string_to_utf8 (minfo->marshaltype);
1813 sigbuffer_add_value (&buf, len);
1814 sigbuffer_add_mem (&buf, str, len);
1817 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1818 sigbuffer_add_value (&buf, 0);
1820 if (minfo->mcookie) {
1821 str = mono_string_to_utf8 (minfo->mcookie);
1823 sigbuffer_add_value (&buf, len);
1824 sigbuffer_add_mem (&buf, str, len);
1827 sigbuffer_add_value (&buf, 0);
1833 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1834 sigbuffer_free (&buf);
1839 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1841 MonoDynamicTable *table;
1844 /* maybe this fixup should be done in the C# code */
1845 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1846 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1847 table = &assembly->tables [MONO_TABLE_FIELD];
1848 fb->table_idx = table->next_idx ++;
1849 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1850 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1851 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1852 values [MONO_FIELD_FLAGS] = fb->attrs;
1853 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1855 if (fb->offset != -1) {
1856 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1858 alloc_table (table, table->rows);
1859 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1860 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1861 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1863 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1864 guint32 field_type = 0;
1865 table = &assembly->tables [MONO_TABLE_CONSTANT];
1867 alloc_table (table, table->rows);
1868 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1869 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1870 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1871 values [MONO_CONSTANT_TYPE] = field_type;
1872 values [MONO_CONSTANT_PADDING] = 0;
1874 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1876 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1878 alloc_table (table, table->rows);
1879 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1880 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1882 * We store it in the code section because it's simpler for now.
1885 if (mono_array_length (fb->rva_data) >= 10)
1886 stream_data_align (&assembly->code);
1887 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1889 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1890 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1892 if (fb->marshal_info) {
1893 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1895 alloc_table (table, table->rows);
1896 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1897 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1898 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1903 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1906 guint32 nparams = 0;
1907 MonoReflectionMethodBuilder *mb = fb->get_method;
1908 MonoReflectionMethodBuilder *smb = fb->set_method;
1911 if (mb && mb->parameters)
1912 nparams = mono_array_length (mb->parameters);
1913 if (!mb && smb && smb->parameters)
1914 nparams = mono_array_length (smb->parameters) - 1;
1915 sigbuffer_init (&buf, 32);
1916 sigbuffer_add_byte (&buf, 0x08);
1917 sigbuffer_add_value (&buf, nparams);
1919 encode_reflection_type (assembly, mb->rtype, &buf);
1920 for (i = 0; i < nparams; ++i) {
1921 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1922 encode_reflection_type (assembly, pt, &buf);
1924 } else if (smb && smb->parameters) {
1925 /* the property type is the last param */
1926 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1927 for (i = 0; i < nparams; ++i) {
1928 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1929 encode_reflection_type (assembly, pt, &buf);
1932 encode_reflection_type (assembly, fb->type, &buf);
1935 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1936 sigbuffer_free (&buf);
1941 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1943 MonoDynamicTable *table;
1945 guint num_methods = 0;
1949 * we need to set things in the following tables:
1950 * PROPERTYMAP (info already filled in _get_type_info ())
1951 * PROPERTY (rows already preallocated in _get_type_info ())
1952 * METHOD (method info already done with the generic method code)
1955 table = &assembly->tables [MONO_TABLE_PROPERTY];
1956 pb->table_idx = table->next_idx ++;
1957 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1958 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1959 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1960 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1962 /* FIXME: we still don't handle 'other' methods */
1963 if (pb->get_method) num_methods ++;
1964 if (pb->set_method) num_methods ++;
1966 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1967 table->rows += num_methods;
1968 alloc_table (table, table->rows);
1970 if (pb->get_method) {
1971 semaidx = table->next_idx ++;
1972 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1973 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1974 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1975 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1977 if (pb->set_method) {
1978 semaidx = table->next_idx ++;
1979 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1980 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1981 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1982 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1987 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1989 MonoDynamicTable *table;
1991 guint num_methods = 0;
1995 * we need to set things in the following tables:
1996 * EVENTMAP (info already filled in _get_type_info ())
1997 * EVENT (rows already preallocated in _get_type_info ())
1998 * METHOD (method info already done with the generic method code)
2001 table = &assembly->tables [MONO_TABLE_EVENT];
2002 eb->table_idx = table->next_idx ++;
2003 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2004 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2005 values [MONO_EVENT_FLAGS] = eb->attrs;
2006 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
2009 * FIXME: we still don't handle 'other' methods
2011 if (eb->add_method) num_methods ++;
2012 if (eb->remove_method) num_methods ++;
2013 if (eb->raise_method) num_methods ++;
2015 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2016 table->rows += num_methods;
2017 alloc_table (table, table->rows);
2019 if (eb->add_method) {
2020 semaidx = table->next_idx ++;
2021 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2022 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2023 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2024 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2026 if (eb->remove_method) {
2027 semaidx = table->next_idx ++;
2028 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2029 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2030 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2031 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2033 if (eb->raise_method) {
2034 semaidx = table->next_idx ++;
2035 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2036 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2037 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2038 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2043 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2045 MonoDynamicTable *table;
2046 guint32 num_constraints, i;
2050 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2051 num_constraints = gparam->iface_constraints ?
2052 mono_array_length (gparam->iface_constraints) : 0;
2053 table->rows += num_constraints;
2054 if (gparam->base_type)
2056 alloc_table (table, table->rows);
2058 if (gparam->base_type) {
2059 table_idx = table->next_idx ++;
2060 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2062 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2063 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2064 assembly, gparam->base_type->type);
2067 for (i = 0; i < num_constraints; i++) {
2068 MonoReflectionType *constraint = mono_array_get (
2069 gparam->iface_constraints, gpointer, i);
2071 table_idx = table->next_idx ++;
2072 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2074 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2075 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2076 assembly, constraint->type);
2081 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2083 GenericParamTableEntry *entry;
2086 * The GenericParam table must be sorted according to the `owner' field.
2087 * We need to do this sorting prior to writing the GenericParamConstraint
2088 * table, since we have to use the final GenericParam table indices there
2089 * and they must also be sorted.
2092 entry = g_new0 (GenericParamTableEntry, 1);
2093 entry->owner = owner;
2094 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2095 MOVING_GC_REGISTER (&entry->gparam);
2096 entry->gparam = gparam;
2098 g_ptr_array_add (assembly->gen_params, entry);
2102 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2104 MonoDynamicTable *table;
2105 MonoGenericParam *param;
2109 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2110 table_idx = table->next_idx ++;
2111 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2113 param = entry->gparam->type.type->data.generic_param;
2115 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2116 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2117 values [MONO_GENERICPARAM_NUMBER] = param->num;
2118 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2120 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2122 encode_constraints (entry->gparam, table_idx, assembly);
2126 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2128 MonoDynamicTable *table;
2131 guint32 cols [MONO_ASSEMBLY_SIZE];
2135 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2138 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2139 table = &assembly->tables [MONO_TABLE_MODULEREF];
2140 token = table->next_idx ++;
2142 alloc_table (table, table->rows);
2143 values = table->values + token * MONO_MODULEREF_SIZE;
2144 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2146 token <<= MONO_RESOLTION_SCOPE_BITS;
2147 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2148 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2153 if (image->assembly->dynamic)
2155 memset (cols, 0, sizeof (cols));
2157 /* image->assembly->image is the manifest module */
2158 image = image->assembly->image;
2159 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2162 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2163 token = table->next_idx ++;
2165 alloc_table (table, table->rows);
2166 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2167 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2168 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2169 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2170 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2171 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2172 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2173 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2174 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2176 if (strcmp ("", image->assembly->aname.culture)) {
2177 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2178 image->assembly->aname.culture);
2181 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2182 guchar pubtoken [9];
2184 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2185 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2187 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2189 token <<= MONO_RESOLTION_SCOPE_BITS;
2190 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2191 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2196 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2198 MonoDynamicTable *table;
2203 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2206 sigbuffer_init (&buf, 32);
2207 switch (type->type) {
2208 case MONO_TYPE_FNPTR:
2210 case MONO_TYPE_SZARRAY:
2211 case MONO_TYPE_ARRAY:
2213 case MONO_TYPE_MVAR:
2214 case MONO_TYPE_GENERICINST:
2215 encode_type (assembly, type, &buf);
2217 case MONO_TYPE_CLASS:
2218 case MONO_TYPE_VALUETYPE: {
2219 MonoClass *k = mono_class_from_mono_type (type);
2220 if (!k || !k->generic_container) {
2221 sigbuffer_free (&buf);
2224 encode_type (assembly, type, &buf);
2228 sigbuffer_free (&buf);
2232 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2233 if (assembly->save) {
2234 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2235 alloc_table (table, table->rows + 1);
2236 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2237 values [MONO_TYPESPEC_SIGNATURE] = token;
2239 sigbuffer_free (&buf);
2241 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2242 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2248 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2250 MonoDynamicTable *table;
2252 guint32 token, scope, enclosing;
2255 /* if the type requires a typespec, we must try that first*/
2256 if (try_typespec && (token = create_typespec (assembly, type)))
2258 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2261 klass = my_mono_class_from_mono_type (type);
2263 klass = mono_class_from_mono_type (type);
2266 * If it's in the same module and not a generic type parameter:
2268 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2269 (type->type != MONO_TYPE_MVAR)) {
2270 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2271 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2272 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2276 if (klass->nested_in) {
2277 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2278 /* get the typeref idx of the enclosing type */
2279 enclosing >>= MONO_TYPEDEFORREF_BITS;
2280 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2282 scope = resolution_scope_from_image (assembly, klass->image);
2284 table = &assembly->tables [MONO_TABLE_TYPEREF];
2285 if (assembly->save) {
2286 alloc_table (table, table->rows + 1);
2287 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2288 values [MONO_TYPEREF_SCOPE] = scope;
2289 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2290 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2292 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2293 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2295 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2300 * Despite the name, we handle also TypeSpec (with the above helper).
2303 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2305 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2309 * Insert a memberef row into the metadata: the token that point to the memberref
2310 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2311 * mono_image_get_fieldref_token()).
2312 * The sig param is an index to an already built signature.
2315 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2317 MonoDynamicTable *table;
2319 guint32 token, pclass;
2322 parent = mono_image_typedef_or_ref (assembly, type);
2323 switch (parent & MONO_TYPEDEFORREF_MASK) {
2324 case MONO_TYPEDEFORREF_TYPEREF:
2325 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2327 case MONO_TYPEDEFORREF_TYPESPEC:
2328 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2330 case MONO_TYPEDEFORREF_TYPEDEF:
2331 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2334 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2337 /* extract the index */
2338 parent >>= MONO_TYPEDEFORREF_BITS;
2340 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2342 if (assembly->save) {
2343 alloc_table (table, table->rows + 1);
2344 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2345 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2346 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2347 values [MONO_MEMBERREF_SIGNATURE] = sig;
2350 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2357 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2360 MonoMethodSignature *sig;
2362 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2364 if (create_typespec) {
2365 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2370 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2371 if (token && !create_typespec)
2374 g_assert (!method->is_inflated);
2377 * A methodref signature can't contain an unmanaged calling convention.
2379 sig = mono_metadata_signature_dup (mono_method_signature (method));
2380 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2381 sig->call_convention = MONO_CALL_DEFAULT;
2382 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2383 method->name, method_encode_signature (assembly, sig));
2385 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2388 if (create_typespec) {
2389 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2390 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2391 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2393 if (assembly->save) {
2396 alloc_table (table, table->rows + 1);
2397 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2398 values [MONO_METHODSPEC_METHOD] = token;
2399 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2402 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2404 /*methodspec and memberef tokens are diferent, */
2405 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2412 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2415 ReflectionMethodBuilder rmb;
2418 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2422 name = mono_string_to_utf8 (method->name);
2423 reflection_methodbuilder_from_method_builder (&rmb, method);
2426 * A methodref signature can't contain an unmanaged calling convention.
2427 * Since some flags are encoded as part of call_conv, we need to check against it.
2429 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2430 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2431 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2432 name, method_builder_encode_signature (assembly, &rmb));
2435 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2440 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2441 const gchar *name, guint32 sig)
2443 MonoDynamicTable *table;
2447 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2449 if (assembly->save) {
2450 alloc_table (table, table->rows + 1);
2451 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2452 values [MONO_MEMBERREF_CLASS] = original;
2453 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2454 values [MONO_MEMBERREF_SIGNATURE] = sig;
2457 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2464 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2468 guint32 nparams = mono_array_length (mb->generic_params);
2471 if (!assembly->save)
2474 sigbuffer_init (&buf, 32);
2476 sigbuffer_add_value (&buf, 0xa);
2477 sigbuffer_add_value (&buf, nparams);
2479 for (i = 0; i < nparams; i++) {
2480 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2481 sigbuffer_add_value (&buf, i);
2484 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2485 sigbuffer_free (&buf);
2490 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2492 MonoDynamicTable *table;
2494 guint32 token, mtoken = 0;
2496 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2500 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2502 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2503 switch (mono_metadata_token_table (mtoken)) {
2504 case MONO_TABLE_MEMBERREF:
2505 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2507 case MONO_TABLE_METHOD:
2508 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2511 g_assert_not_reached ();
2514 if (assembly->save) {
2515 alloc_table (table, table->rows + 1);
2516 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2517 values [MONO_METHODSPEC_METHOD] = mtoken;
2518 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2521 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2524 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2529 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2533 if (mb->generic_params && create_methodspec)
2534 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2536 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2540 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2541 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2546 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2549 ReflectionMethodBuilder rmb;
2552 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2556 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2558 name = mono_string_to_utf8 (rmb.name);
2559 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2560 name, method_builder_encode_signature (assembly, &rmb));
2563 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2568 is_field_on_inst (MonoClassField *field)
2570 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2574 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2577 get_field_on_inst_generic_type (MonoClassField *field)
2579 MonoDynamicGenericClass *dgclass;
2582 g_assert (is_field_on_inst (field));
2584 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2585 field_index = field - dgclass->fields;
2587 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2588 return dgclass->field_generic_types [field_index];
2592 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2596 MonoClassField *field;
2598 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2601 g_assert (f->field->parent);
2604 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2605 int index = field - field->parent->fields;
2606 type = field->parent->generic_class->container_class->fields [index].type;
2608 if (is_field_on_inst (f->field))
2609 type = get_field_on_inst_generic_type (f->field);
2611 type = f->field->type;
2613 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2614 mono_field_get_name (f->field),
2615 fieldref_encode_signature (assembly, type));
2616 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2621 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2625 MonoGenericClass *gclass;
2626 MonoDynamicGenericClass *dgclass;
2627 MonoReflectionFieldBuilder *fb = f->fb;
2630 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2633 klass = mono_class_from_mono_type (f->inst->type.type);
2634 gclass = f->inst->type.type->data.generic_class;
2635 g_assert (gclass->is_dynamic);
2636 dgclass = (MonoDynamicGenericClass *) gclass;
2638 name = mono_string_to_utf8 (fb->name);
2639 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2640 field_encode_signature (assembly, fb));
2642 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2647 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2651 MonoGenericClass *gclass;
2652 MonoDynamicGenericClass *dgclass;
2653 MonoReflectionCtorBuilder *cb = c->cb;
2654 ReflectionMethodBuilder rmb;
2657 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2659 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2662 klass = mono_class_from_mono_type (c->inst->type.type);
2663 gclass = c->inst->type.type->data.generic_class;
2664 g_assert (gclass->is_dynamic);
2665 dgclass = (MonoDynamicGenericClass *) gclass;
2667 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2669 name = mono_string_to_utf8 (rmb.name);
2671 sig = method_builder_encode_signature (assembly, &rmb);
2673 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2676 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2681 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2685 MonoGenericClass *gclass;
2686 MonoReflectionMethodBuilder *mb = m->mb;
2687 ReflectionMethodBuilder rmb;
2690 if (create_methodspec && mb->generic_params)
2692 g_assert_not_reached ();
2694 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2697 klass = mono_class_from_mono_type (m->inst->type.type);
2698 gclass = m->inst->type.type->data.generic_class;
2699 g_assert (gclass->is_dynamic);
2701 reflection_methodbuilder_from_method_builder (&rmb, mb);
2703 name = mono_string_to_utf8 (rmb.name);
2705 sig = method_builder_encode_signature (assembly, &rmb);
2707 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2710 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2715 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2719 guint32 nparams = context->method_inst->type_argc;
2722 if (!assembly->save)
2725 sigbuffer_init (&buf, 32);
2727 * FIXME: vararg, explicit_this, differenc call_conv values...
2729 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2730 sigbuffer_add_value (&buf, nparams);
2732 for (i = 0; i < nparams; i++)
2733 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2735 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2736 sigbuffer_free (&buf);
2741 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2743 MonoDynamicTable *table;
2745 guint32 token, mtoken = 0, sig;
2746 MonoMethodInflated *imethod;
2747 MonoMethod *declaring;
2749 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2751 g_assert (method->is_inflated);
2752 imethod = (MonoMethodInflated *) method;
2753 declaring = imethod->declaring;
2755 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2756 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2758 if (!mono_method_signature (declaring)->generic_param_count)
2761 switch (mono_metadata_token_table (mtoken)) {
2762 case MONO_TABLE_MEMBERREF:
2763 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2765 case MONO_TABLE_METHOD:
2766 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2769 g_assert_not_reached ();
2772 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2774 if (assembly->save) {
2775 alloc_table (table, table->rows + 1);
2776 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2777 values [MONO_METHODSPEC_METHOD] = mtoken;
2778 values [MONO_METHODSPEC_SIGNATURE] = sig;
2781 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2788 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2790 MonoMethodInflated *imethod;
2793 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2797 g_assert (method->is_inflated);
2798 imethod = (MonoMethodInflated *) method;
2800 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2801 token = method_encode_methodspec (assembly, method);
2803 guint32 sig = method_encode_signature (
2804 assembly, mono_method_signature (imethod->declaring));
2805 token = mono_image_get_memberref_token (
2806 assembly, &method->klass->byval_arg, method->name, sig);
2809 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2814 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2816 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2819 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2820 token = mono_image_get_memberref_token (
2821 assembly, &m->klass->byval_arg, m->name, sig);
2827 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2829 MonoDynamicTable *table;
2837 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2838 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2839 * Because of this, we must not insert it into the `typeref' hash table.
2842 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2846 sigbuffer_init (&buf, 32);
2848 g_assert (tb->generic_params);
2849 klass = mono_class_from_mono_type (tb->type.type);
2851 if (tb->generic_container)
2852 mono_reflection_create_generic_class (tb);
2854 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2855 g_assert (klass->generic_container);
2856 sigbuffer_add_value (&buf, klass->byval_arg.type);
2857 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2859 count = mono_array_length (tb->generic_params);
2860 sigbuffer_add_value (&buf, count);
2861 for (i = 0; i < count; i++) {
2862 MonoReflectionGenericParam *gparam;
2864 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2866 encode_type (assembly, gparam->type.type, &buf);
2869 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2871 if (assembly->save) {
2872 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2873 alloc_table (table, table->rows + 1);
2874 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2875 values [MONO_TYPESPEC_SIGNATURE] = token;
2877 sigbuffer_free (&buf);
2879 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2880 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2886 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2889 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2891 int i, count, len, pos;
2896 count += mono_array_length (modreq);
2898 count += mono_array_length (modopt);
2901 return mono_metadata_type_dup (NULL, type);
2903 len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
2905 memcpy (t, type, len);
2907 t->num_mods = count;
2910 for (i = 0; i < mono_array_length (modreq); ++i) {
2911 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
2912 t->modifiers [pos].required = 1;
2913 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2918 for (i = 0; i < mono_array_length (modopt); ++i) {
2919 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
2920 t->modifiers [pos].required = 0;
2921 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2930 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2932 MonoDynamicTable *table;
2934 MonoType *custom = NULL;
2936 guint32 token, pclass, parent, sig;
2939 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2943 klass = mono_class_from_mono_type (fb->typeb->type);
2944 name = mono_string_to_utf8 (fb->name);
2946 /* fb->type does not include the custom modifiers */
2947 /* FIXME: We should do this in one place when a fieldbuilder is created */
2948 if (fb->modreq || fb->modopt) {
2949 custom = add_custom_modifiers (assembly, fb->type->type, fb->modreq, fb->modopt);
2950 sig = fieldref_encode_signature (assembly, custom);
2953 sig = fieldref_encode_signature (assembly, fb->type->type);
2956 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2957 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2959 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2960 parent >>= MONO_TYPEDEFORREF_BITS;
2962 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2964 if (assembly->save) {
2965 alloc_table (table, table->rows + 1);
2966 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2967 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2968 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2969 values [MONO_MEMBERREF_SIGNATURE] = sig;
2972 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2974 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2980 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2987 if (!assembly->save)
2990 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2991 g_assert (helper->type == 2);
2993 if (helper->arguments)
2994 nargs = mono_array_length (helper->arguments);
2998 size = 10 + (nargs * 10);
3000 sigbuffer_init (&buf, 32);
3002 /* Encode calling convention */
3003 /* Change Any to Standard */
3004 if ((helper->call_conv & 0x03) == 0x03)
3005 helper->call_conv = 0x01;
3006 /* explicit_this implies has_this */
3007 if (helper->call_conv & 0x40)
3008 helper->call_conv &= 0x20;
3010 if (helper->call_conv == 0) { /* Unmanaged */
3011 idx = helper->unmanaged_call_conv - 1;
3014 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3015 if (helper->call_conv & 0x02) /* varargs */
3019 sigbuffer_add_byte (&buf, idx);
3020 sigbuffer_add_value (&buf, nargs);
3021 encode_reflection_type (assembly, helper->return_type, &buf);
3022 for (i = 0; i < nargs; ++i) {
3023 MonoArray *modreqs = NULL;
3024 MonoArray *modopts = NULL;
3025 MonoReflectionType *pt;
3027 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3028 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3029 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3030 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3032 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3033 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3034 encode_reflection_type (assembly, pt, &buf);
3036 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3037 sigbuffer_free (&buf);
3043 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3046 MonoDynamicTable *table;
3049 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3050 idx = table->next_idx ++;
3052 alloc_table (table, table->rows);
3053 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3055 values [MONO_STAND_ALONE_SIGNATURE] =
3056 mono_reflection_encode_sighelper (assembly, helper);
3062 reflection_cc_to_file (int call_conv) {
3063 switch (call_conv & 0x3) {
3065 case 1: return MONO_CALL_DEFAULT;
3066 case 2: return MONO_CALL_VARARG;
3068 g_assert_not_reached ();
3075 MonoMethodSignature *sig;
3081 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3086 MonoMethodSignature *sig;
3089 name = mono_string_to_utf8 (m->name);
3090 nparams = mono_array_length (m->parameters);
3091 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
3093 sig->sentinelpos = -1;
3094 sig->call_convention = reflection_cc_to_file (m->call_conv);
3095 sig->param_count = nparams;
3096 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
3097 for (i = 0; i < nparams; ++i) {
3098 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
3099 sig->params [i] = t->type;
3102 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3104 if (strcmp (name, am->name) == 0 &&
3105 mono_metadata_type_equal (am->parent, m->parent->type) &&
3106 mono_metadata_signature_equal (am->sig, sig)) {
3109 m->table_idx = am->token & 0xffffff;
3113 am = g_new0 (ArrayMethod, 1);
3116 am->parent = m->parent->type;
3117 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3118 method_encode_signature (assembly, sig));
3119 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3120 m->table_idx = am->token & 0xffffff;
3125 * Insert into the metadata tables all the info about the TypeBuilder tb.
3126 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3129 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3131 MonoDynamicTable *table;
3133 int i, is_object = 0, is_system = 0;
3136 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3137 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3138 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3139 n = mono_string_to_utf8 (tb->name);
3140 if (strcmp (n, "Object") == 0)
3142 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3144 n = mono_string_to_utf8 (tb->nspace);
3145 if (strcmp (n, "System") == 0)
3147 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3149 if (tb->parent && !(is_system && is_object) &&
3150 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3151 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
3153 values [MONO_TYPEDEF_EXTENDS] = 0;
3155 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3156 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3159 * if we have explicitlayout or sequentiallayouts, output data in the
3160 * ClassLayout table.
3162 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3163 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3164 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3166 alloc_table (table, table->rows);
3167 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3168 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3169 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3170 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3173 /* handle interfaces */
3174 if (tb->interfaces) {
3175 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3177 table->rows += mono_array_length (tb->interfaces);
3178 alloc_table (table, table->rows);
3179 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3180 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3181 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3182 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3183 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3184 values += MONO_INTERFACEIMPL_SIZE;
3190 table = &assembly->tables [MONO_TABLE_FIELD];
3191 table->rows += tb->num_fields;
3192 alloc_table (table, table->rows);
3193 for (i = 0; i < tb->num_fields; ++i)
3194 mono_image_get_field_info (
3195 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3198 /* handle constructors */
3200 table = &assembly->tables [MONO_TABLE_METHOD];
3201 table->rows += mono_array_length (tb->ctors);
3202 alloc_table (table, table->rows);
3203 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3204 mono_image_get_ctor_info (domain,
3205 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3208 /* handle methods */
3210 table = &assembly->tables [MONO_TABLE_METHOD];
3211 table->rows += tb->num_methods;
3212 alloc_table (table, table->rows);
3213 for (i = 0; i < tb->num_methods; ++i)
3214 mono_image_get_method_info (
3215 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3218 /* Do the same with properties etc.. */
3219 if (tb->events && mono_array_length (tb->events)) {
3220 table = &assembly->tables [MONO_TABLE_EVENT];
3221 table->rows += mono_array_length (tb->events);
3222 alloc_table (table, table->rows);
3223 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3225 alloc_table (table, table->rows);
3226 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3227 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3228 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3229 for (i = 0; i < mono_array_length (tb->events); ++i)
3230 mono_image_get_event_info (
3231 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3233 if (tb->properties && mono_array_length (tb->properties)) {
3234 table = &assembly->tables [MONO_TABLE_PROPERTY];
3235 table->rows += mono_array_length (tb->properties);
3236 alloc_table (table, table->rows);
3237 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3239 alloc_table (table, table->rows);
3240 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3241 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3242 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3243 for (i = 0; i < mono_array_length (tb->properties); ++i)
3244 mono_image_get_property_info (
3245 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3248 /* handle generic parameters */
3249 if (tb->generic_params) {
3250 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3251 table->rows += mono_array_length (tb->generic_params);
3252 alloc_table (table, table->rows);
3253 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3254 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3256 mono_image_get_generic_param_info (
3257 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3261 mono_image_add_decl_security (assembly,
3262 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3265 MonoDynamicTable *ntable;
3267 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3268 ntable->rows += mono_array_length (tb->subtypes);
3269 alloc_table (ntable, ntable->rows);
3270 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3272 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3273 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3275 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3276 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3277 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3278 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3279 mono_string_to_utf8 (tb->name), tb->table_idx,
3280 ntable->next_idx, ntable->rows);*/
3281 values += MONO_NESTED_CLASS_SIZE;
3288 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3292 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3294 if (!type->subtypes)
3297 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3298 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3299 collect_types (types, subtype);
3304 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3306 if ((*type1)->table_idx < (*type2)->table_idx)
3309 if ((*type1)->table_idx > (*type2)->table_idx)
3316 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3321 for (i = 0; i < mono_array_length (pinfo); ++i) {
3322 MonoReflectionParamBuilder *pb;
3323 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3326 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3331 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3334 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3336 for (i = 0; i < tb->num_fields; ++i) {
3337 MonoReflectionFieldBuilder* fb;
3338 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3339 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3343 for (i = 0; i < mono_array_length (tb->events); ++i) {
3344 MonoReflectionEventBuilder* eb;
3345 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3346 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3349 if (tb->properties) {
3350 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3351 MonoReflectionPropertyBuilder* pb;
3352 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3353 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3357 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3358 MonoReflectionCtorBuilder* cb;
3359 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3360 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3361 params_add_cattrs (assembly, cb->pinfo);
3366 for (i = 0; i < tb->num_methods; ++i) {
3367 MonoReflectionMethodBuilder* mb;
3368 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3369 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3370 params_add_cattrs (assembly, mb->pinfo);
3375 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3376 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3381 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3385 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3387 if (moduleb->global_methods) {
3388 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3389 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3390 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3391 params_add_cattrs (assembly, mb->pinfo);
3395 if (moduleb->global_fields) {
3396 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3397 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3398 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3402 if (moduleb->types) {
3403 for (i = 0; i < moduleb->num_types; ++i)
3404 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3409 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3411 MonoDynamicTable *table;
3415 char *b = blob_size;
3418 table = &assembly->tables [MONO_TABLE_FILE];
3420 alloc_table (table, table->rows);
3421 values = table->values + table->next_idx * MONO_FILE_SIZE;
3422 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3423 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3424 if (module->image->dynamic) {
3425 /* This depends on the fact that the main module is emitted last */
3426 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3427 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3430 path = g_strdup (module->image->name);
3432 mono_sha1_get_digest_from_file (path, hash);
3435 mono_metadata_encode_value (20, b, &b);
3436 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3437 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3442 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3444 MonoDynamicTable *table;
3447 table = &assembly->tables [MONO_TABLE_MODULE];
3448 mb->table_idx = table->next_idx ++;
3449 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3450 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3453 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3454 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3455 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3456 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3460 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3461 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3463 MonoDynamicTable *table;
3467 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3468 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3471 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3473 alloc_table (table, table->rows);
3474 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3476 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3477 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3478 if (klass->nested_in)
3479 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3481 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3482 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3483 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3485 res = table->next_idx;
3489 /* Emit nested types */
3490 if (klass->nested_classes) {
3493 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3494 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3501 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3502 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3507 klass = mono_class_from_mono_type (tb->type.type);
3509 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3511 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3512 parent_index, assembly);
3516 * We need to do this ourselves since klass->nested_classes is not set up.
3519 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3520 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3525 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3526 guint32 module_index, MonoDynamicImage *assembly)
3528 MonoImage *image = module->image;
3532 t = &image->tables [MONO_TABLE_TYPEDEF];
3534 for (i = 0; i < t->rows; ++i) {
3535 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3537 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3538 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3543 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3545 MonoDynamicTable *table;
3551 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3553 if (assemblyb->type_forwarders) {
3554 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3555 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3561 klass = mono_class_from_mono_type (t->type);
3563 scope = resolution_scope_from_image (assembly, klass->image);
3564 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3565 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3568 alloc_table (table, table->rows);
3569 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3571 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3572 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3573 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3574 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3575 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3582 #define align_pointer(base,p)\
3584 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3586 (p) += 4 - (__diff & 3);\
3590 compare_constants (const void *a, const void *b)
3592 const guint32 *a_values = a;
3593 const guint32 *b_values = b;
3594 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3598 compare_semantics (const void *a, const void *b)
3600 const guint32 *a_values = a;
3601 const guint32 *b_values = b;
3602 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3605 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3609 compare_custom_attrs (const void *a, const void *b)
3611 const guint32 *a_values = a;
3612 const guint32 *b_values = b;
3614 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3618 compare_field_marshal (const void *a, const void *b)
3620 const guint32 *a_values = a;
3621 const guint32 *b_values = b;
3623 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3627 compare_nested (const void *a, const void *b)
3629 const guint32 *a_values = a;
3630 const guint32 *b_values = b;
3632 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3636 compare_genericparam (const void *a, const void *b)
3638 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3639 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3641 if ((*b_entry)->owner == (*a_entry)->owner)
3643 (*a_entry)->gparam->type.type->data.generic_param->num -
3644 (*b_entry)->gparam->type.type->data.generic_param->num;
3646 return (*a_entry)->owner - (*b_entry)->owner;
3650 compare_declsecurity_attrs (const void *a, const void *b)
3652 const guint32 *a_values = a;
3653 const guint32 *b_values = b;
3655 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3659 compare_interface_impl (const void *a, const void *b)
3661 const guint32 *a_values = a;
3662 const guint32 *b_values = b;
3664 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3668 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3672 pad_heap (MonoDynamicStream *sh)
3674 if (sh->index & 3) {
3675 int sz = 4 - (sh->index & 3);
3676 memset (sh->data + sh->index, 0, sz);
3683 MonoDynamicStream *stream;
3687 * build_compressed_metadata() fills in the blob of data that represents the
3688 * raw metadata as it will be saved in the PE file. The five streams are output
3689 * and the metadata tables are comnpressed from the guint32 array representation,
3690 * to the compressed on-disk format.
3693 build_compressed_metadata (MonoDynamicImage *assembly)
3695 MonoDynamicTable *table;
3697 guint64 valid_mask = 0;
3698 guint64 sorted_mask;
3699 guint32 heapt_size = 0;
3700 guint32 meta_size = 256; /* allow for header and other stuff */
3701 guint32 table_offset;
3702 guint32 ntables = 0;
3708 struct StreamDesc stream_desc [5];
3710 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3711 for (i = 0; i < assembly->gen_params->len; i++){
3712 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3713 write_generic_param_entry (assembly, entry);
3716 stream_desc [0].name = "#~";
3717 stream_desc [0].stream = &assembly->tstream;
3718 stream_desc [1].name = "#Strings";
3719 stream_desc [1].stream = &assembly->sheap;
3720 stream_desc [2].name = "#US";
3721 stream_desc [2].stream = &assembly->us;
3722 stream_desc [3].name = "#Blob";
3723 stream_desc [3].stream = &assembly->blob;
3724 stream_desc [4].name = "#GUID";
3725 stream_desc [4].stream = &assembly->guid;
3727 /* tables that are sorted */
3728 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3729 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3730 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3731 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3732 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3733 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3734 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3736 /* Compute table sizes */
3737 /* the MonoImage has already been created in mono_image_basic_init() */
3738 meta = &assembly->image;
3740 /* sizes should be multiple of 4 */
3741 pad_heap (&assembly->blob);
3742 pad_heap (&assembly->guid);
3743 pad_heap (&assembly->sheap);
3744 pad_heap (&assembly->us);
3746 /* Setup the info used by compute_sizes () */
3747 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3748 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3749 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3751 meta_size += assembly->blob.index;
3752 meta_size += assembly->guid.index;
3753 meta_size += assembly->sheap.index;
3754 meta_size += assembly->us.index;
3756 for (i=0; i < MONO_TABLE_NUM; ++i)
3757 meta->tables [i].rows = assembly->tables [i].rows;
3759 for (i = 0; i < MONO_TABLE_NUM; i++){
3760 if (meta->tables [i].rows == 0)
3762 valid_mask |= (guint64)1 << i;
3764 meta->tables [i].row_size = mono_metadata_compute_size (
3765 meta, i, &meta->tables [i].size_bitfield);
3766 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3768 heapt_size += 24; /* #~ header size */
3769 heapt_size += ntables * 4;
3770 /* make multiple of 4 */
3773 meta_size += heapt_size;
3774 meta->raw_metadata = g_malloc0 (meta_size);
3775 p = (unsigned char*)meta->raw_metadata;
3776 /* the metadata signature */
3777 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3778 /* version numbers and 4 bytes reserved */
3779 int16val = (guint16*)p;
3780 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3781 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3783 /* version string */
3784 int32val = (guint32*)p;
3785 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3787 memcpy (p, meta->version, strlen (meta->version));
3788 p += GUINT32_FROM_LE (*int32val);
3789 align_pointer (meta->raw_metadata, p);
3790 int16val = (guint16*)p;
3791 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3792 *int16val = GUINT16_TO_LE (5); /* number of streams */
3796 * write the stream info.
3798 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3799 table_offset += 3; table_offset &= ~3;
3801 assembly->tstream.index = heapt_size;
3802 for (i = 0; i < 5; ++i) {
3803 int32val = (guint32*)p;
3804 stream_desc [i].stream->offset = table_offset;
3805 *int32val++ = GUINT32_TO_LE (table_offset);
3806 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3807 table_offset += GUINT32_FROM_LE (*int32val);
3808 table_offset += 3; table_offset &= ~3;
3810 strcpy ((char*)p, stream_desc [i].name);
3811 p += strlen (stream_desc [i].name) + 1;
3812 align_pointer (meta->raw_metadata, p);
3815 * now copy the data, the table stream header and contents goes first.
3817 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3818 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3819 int32val = (guint32*)p;
3820 *int32val = GUINT32_TO_LE (0); /* reserved */
3823 if (mono_framework_version () > 1) {
3824 *p++ = 2; /* version */
3827 *p++ = 1; /* version */
3831 if (meta->idx_string_wide)
3833 if (meta->idx_guid_wide)
3835 if (meta->idx_blob_wide)
3838 *p++ = 1; /* reserved */
3839 int64val = (guint64*)p;
3840 *int64val++ = GUINT64_TO_LE (valid_mask);
3841 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3843 int32val = (guint32*)p;
3844 for (i = 0; i < MONO_TABLE_NUM; i++){
3845 if (meta->tables [i].rows == 0)
3847 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3849 p = (unsigned char*)int32val;
3851 /* sort the tables that still need sorting */
3852 table = &assembly->tables [MONO_TABLE_CONSTANT];
3854 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3855 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3857 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3858 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3860 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3861 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3863 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3864 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3866 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3867 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3868 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3870 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3871 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3873 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3875 /* compress the tables */
3876 for (i = 0; i < MONO_TABLE_NUM; i++){
3879 guint32 bitfield = meta->tables [i].size_bitfield;
3880 if (!meta->tables [i].rows)
3882 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3883 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3884 meta->tables [i].base = (char*)p;
3885 for (row = 1; row <= meta->tables [i].rows; ++row) {
3886 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3887 for (col = 0; col < assembly->tables [i].columns; ++col) {
3888 switch (mono_metadata_table_size (bitfield, col)) {
3890 *p++ = values [col];
3893 *p++ = values [col] & 0xff;
3894 *p++ = (values [col] >> 8) & 0xff;
3897 *p++ = values [col] & 0xff;
3898 *p++ = (values [col] >> 8) & 0xff;
3899 *p++ = (values [col] >> 16) & 0xff;
3900 *p++ = (values [col] >> 24) & 0xff;
3903 g_assert_not_reached ();
3907 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3910 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3911 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3912 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3913 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3914 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3916 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3920 * Some tables in metadata need to be sorted according to some criteria, but
3921 * when methods and fields are first created with reflection, they may be assigned a token
3922 * that doesn't correspond to the final token they will get assigned after the sorting.
3923 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3924 * with the reflection objects that represent them. Once all the tables are set up, the
3925 * reflection objects will contains the correct table index. fixup_method() will fixup the
3926 * tokens for the method with ILGenerator @ilgen.
3929 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3931 guint32 code_idx = GPOINTER_TO_UINT (value);
3932 MonoReflectionILTokenInfo *iltoken;
3933 MonoReflectionFieldBuilder *field;
3934 MonoReflectionCtorBuilder *ctor;
3935 MonoReflectionMethodBuilder *method;
3936 MonoReflectionTypeBuilder *tb;
3937 MonoReflectionArrayMethod *am;
3939 unsigned char *target;
3941 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3942 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3943 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3944 switch (target [3]) {
3945 case MONO_TABLE_FIELD:
3946 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3947 field = (MonoReflectionFieldBuilder *)iltoken->member;
3948 idx = field->table_idx;
3949 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3950 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3951 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3953 g_assert_not_reached ();
3956 case MONO_TABLE_METHOD:
3957 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3958 method = (MonoReflectionMethodBuilder *)iltoken->member;
3959 idx = method->table_idx;
3960 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3961 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3962 idx = ctor->table_idx;
3963 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3964 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3965 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3966 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3968 g_assert_not_reached ();
3971 case MONO_TABLE_TYPEDEF:
3972 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3973 g_assert_not_reached ();
3974 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3975 idx = tb->table_idx;
3977 case MONO_TABLE_MEMBERREF:
3978 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3979 am = (MonoReflectionArrayMethod*)iltoken->member;
3980 idx = am->table_idx;
3981 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3982 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3983 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3984 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3985 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3986 g_assert (m->klass->generic_class || m->klass->generic_container);
3988 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3990 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3991 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3992 g_assert (is_field_on_inst (f));
3994 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3995 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3997 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3999 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4001 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4004 g_assert_not_reached ();
4007 case MONO_TABLE_METHODSPEC:
4008 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4009 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4010 g_assert (mono_method_signature (m)->generic_param_count);
4012 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4015 g_assert_not_reached ();
4019 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4021 target [0] = idx & 0xff;
4022 target [1] = (idx >> 8) & 0xff;
4023 target [2] = (idx >> 16) & 0xff;
4030 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4031 * value is not known when the table is emitted.
4034 fixup_cattrs (MonoDynamicImage *assembly)
4036 MonoDynamicTable *table;
4038 guint32 type, i, idx, token;
4041 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4043 for (i = 0; i < table->rows; ++i) {
4044 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4046 type = values [MONO_CUSTOM_ATTR_TYPE];
4047 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4048 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4049 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4050 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4053 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4054 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4055 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4056 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4063 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4065 MonoDynamicTable *table;
4068 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4070 alloc_table (table, table->rows);
4071 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4072 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4073 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4074 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4075 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4080 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4082 MonoDynamicTable *table;
4086 char *b = blob_size;
4088 guint32 idx, offset;
4090 if (rsrc->filename) {
4091 name = mono_string_to_utf8 (rsrc->filename);
4092 sname = g_path_get_basename (name);
4094 table = &assembly->tables [MONO_TABLE_FILE];
4096 alloc_table (table, table->rows);
4097 values = table->values + table->next_idx * MONO_FILE_SIZE;
4098 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4099 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4102 mono_sha1_get_digest_from_file (name, hash);
4103 mono_metadata_encode_value (20, b, &b);
4104 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4105 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4107 idx = table->next_idx++;
4109 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4115 data = mono_array_addr (rsrc->data, char, 0);
4116 len = mono_array_length (rsrc->data);
4122 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4123 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4124 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4125 mono_image_add_stream_data (&assembly->resources, data, len);
4129 * The entry should be emitted into the MANIFESTRESOURCE table of
4130 * the main module, but that needs to reference the FILE table
4131 * which isn't emitted yet.
4138 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4142 set_version_from_string (MonoString *version, guint32 *values)
4144 gchar *ver, *p, *str;
4147 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4148 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4149 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4150 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4153 ver = str = mono_string_to_utf8 (version);
4154 for (i = 0; i < 4; ++i) {
4155 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4161 /* handle Revision and Build */
4171 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4175 char *b = blob_size;
4180 len = mono_array_length (pkey);
4181 mono_metadata_encode_value (len, b, &b);
4182 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4183 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4185 assembly->public_key = g_malloc (len);
4186 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4187 assembly->public_key_len = len;
4189 /* Special case: check for ECMA key (16 bytes) */
4190 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4191 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4192 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4193 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4194 /* minimum key size (in 2.0) is 384 bits */
4195 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4197 /* FIXME - verifier */
4198 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4199 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4201 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4207 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4209 MonoDynamicTable *table;
4210 MonoDynamicImage *assembly;
4211 MonoReflectionAssemblyBuilder *assemblyb;
4215 guint32 module_index;
4217 assemblyb = moduleb->assemblyb;
4218 assembly = moduleb->dynamic_image;
4219 domain = mono_object_domain (assemblyb);
4221 /* Emit ASSEMBLY table */
4222 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4223 alloc_table (table, 1);
4224 values = table->values + MONO_ASSEMBLY_SIZE;
4225 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4226 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4227 if (assemblyb->culture) {
4228 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4230 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4232 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4233 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4234 set_version_from_string (assemblyb->version, values);
4236 /* Emit FILE + EXPORTED_TYPE table */
4238 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4240 MonoReflectionModuleBuilder *file_module =
4241 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4242 if (file_module != moduleb) {
4243 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4245 if (file_module->types) {
4246 for (j = 0; j < file_module->num_types; ++j) {
4247 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4248 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4253 if (assemblyb->loaded_modules) {
4254 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4255 MonoReflectionModule *file_module =
4256 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4257 mono_image_fill_file_table (domain, file_module, assembly);
4259 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4262 if (assemblyb->type_forwarders)
4263 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4265 /* Emit MANIFESTRESOURCE table */
4267 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4269 MonoReflectionModuleBuilder *file_module =
4270 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4271 /* The table for the main module is emitted later */
4272 if (file_module != moduleb) {
4274 if (file_module->resources) {
4275 int len = mono_array_length (file_module->resources);
4276 for (j = 0; j < len; ++j) {
4277 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4278 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4285 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4288 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4289 * for the modulebuilder @moduleb.
4290 * At the end of the process, method and field tokens are fixed up and the
4291 * on-disk compressed metadata representation is created.
4294 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4296 MonoDynamicTable *table;
4297 MonoDynamicImage *assembly;
4298 MonoReflectionAssemblyBuilder *assemblyb;
4304 assemblyb = moduleb->assemblyb;
4305 assembly = moduleb->dynamic_image;
4306 domain = mono_object_domain (assemblyb);
4308 if (assembly->text_rva)
4311 assembly->text_rva = START_TEXT_RVA;
4313 if (moduleb->is_main) {
4314 mono_image_emit_manifest (moduleb);
4317 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4318 table->rows = 1; /* .<Module> */
4320 alloc_table (table, table->rows);
4322 * Set the first entry.
4324 values = table->values + table->columns;
4325 values [MONO_TYPEDEF_FLAGS] = 0;
4326 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4327 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4328 values [MONO_TYPEDEF_EXTENDS] = 0;
4329 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4330 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4333 * handle global methods
4334 * FIXME: test what to do when global methods are defined in multiple modules.
4336 if (moduleb->global_methods) {
4337 table = &assembly->tables [MONO_TABLE_METHOD];
4338 table->rows += mono_array_length (moduleb->global_methods);
4339 alloc_table (table, table->rows);
4340 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4341 mono_image_get_method_info (
4342 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4344 if (moduleb->global_fields) {
4345 table = &assembly->tables [MONO_TABLE_FIELD];
4346 table->rows += mono_array_length (moduleb->global_fields);
4347 alloc_table (table, table->rows);
4348 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4349 mono_image_get_field_info (
4350 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4353 table = &assembly->tables [MONO_TABLE_MODULE];
4354 alloc_table (table, 1);
4355 mono_image_fill_module_table (domain, moduleb, assembly);
4357 /* Collect all types into a list sorted by their table_idx */
4358 types = g_ptr_array_new ();
4361 for (i = 0; i < moduleb->num_types; ++i) {
4362 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4363 collect_types (types, type);
4366 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4367 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4368 table->rows += types->len;
4369 alloc_table (table, table->rows);
4372 * Emit type names + namespaces at one place inside the string heap,
4373 * so load_class_names () needs to touch fewer pages.
4375 for (i = 0; i < types->len; ++i) {
4376 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4377 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4379 for (i = 0; i < types->len; ++i) {
4380 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4381 string_heap_insert_mstring (&assembly->sheap, tb->name);
4384 for (i = 0; i < types->len; ++i) {
4385 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4386 mono_image_get_type_info (domain, type, assembly);
4390 * table->rows is already set above and in mono_image_fill_module_table.
4392 /* add all the custom attributes at the end, once all the indexes are stable */
4393 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4395 /* CAS assembly permissions */
4396 if (assemblyb->permissions_minimum)
4397 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4398 if (assemblyb->permissions_optional)
4399 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4400 if (assemblyb->permissions_refused)
4401 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4403 module_add_cattrs (assembly, moduleb);
4406 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4408 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4409 * the final tokens and don't need another fixup pass. */
4411 if (moduleb->global_methods) {
4412 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4413 MonoReflectionMethodBuilder *mb = mono_array_get (
4414 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4415 mono_image_add_methodimpl (assembly, mb);
4419 for (i = 0; i < types->len; ++i) {
4420 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4421 if (type->methods) {
4422 for (j = 0; j < type->num_methods; ++j) {
4423 MonoReflectionMethodBuilder *mb = mono_array_get (
4424 type->methods, MonoReflectionMethodBuilder*, j);
4426 mono_image_add_methodimpl (assembly, mb);
4431 g_ptr_array_free (types, TRUE);
4433 fixup_cattrs (assembly);
4436 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4439 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4441 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4444 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4446 #ifndef DISABLE_REFLECTION_EMIT
4449 * mono_image_insert_string:
4450 * @module: module builder object
4453 * Insert @str into the user string stream of @module.
4456 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4458 MonoDynamicImage *assembly;
4463 MONO_ARCH_SAVE_REGS;
4465 if (!module->dynamic_image)
4466 mono_image_module_basic_init (module);
4468 assembly = module->dynamic_image;
4470 if (assembly->save) {
4471 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4472 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4473 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4475 char *swapped = g_malloc (2 * mono_string_length (str));
4476 const char *p = (const char*)mono_string_chars (str);
4478 swap_with_size (swapped, p, 2, mono_string_length (str));
4479 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4483 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4485 mono_image_add_stream_data (&assembly->us, "", 1);
4487 idx = assembly->us.index ++;
4490 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4492 return MONO_TOKEN_STRING | idx;
4496 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4501 klass = obj->vtable->klass;
4502 if (strcmp (klass->name, "MonoMethod") == 0) {
4503 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4504 MonoMethodSignature *sig, *old;
4505 guint32 sig_token, parent;
4508 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4510 nargs = mono_array_length (opt_param_types);
4511 old = mono_method_signature (method);
4512 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4514 sig->hasthis = old->hasthis;
4515 sig->explicit_this = old->explicit_this;
4516 sig->call_convention = old->call_convention;
4517 sig->generic_param_count = old->generic_param_count;
4518 sig->param_count = old->param_count + nargs;
4519 sig->sentinelpos = old->param_count;
4520 sig->ret = old->ret;
4522 for (i = 0; i < old->param_count; i++)
4523 sig->params [i] = old->params [i];
4525 for (i = 0; i < nargs; i++) {
4526 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4527 sig->params [old->param_count + i] = rt->type;
4530 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4531 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4532 parent >>= MONO_TYPEDEFORREF_BITS;
4534 parent <<= MONO_MEMBERREF_PARENT_BITS;
4535 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4537 sig_token = method_encode_signature (assembly, sig);
4538 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4539 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4540 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4541 ReflectionMethodBuilder rmb;
4542 guint32 parent, sig;
4545 reflection_methodbuilder_from_method_builder (&rmb, mb);
4546 rmb.opt_types = opt_param_types;
4548 sig = method_builder_encode_signature (assembly, &rmb);
4550 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4551 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4553 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4554 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4556 name = mono_string_to_utf8 (rmb.name);
4557 token = mono_image_get_varargs_method_token (
4558 assembly, parent, name, sig);
4561 g_error ("requested method token for %s\n", klass->name);
4568 * mono_image_create_token:
4569 * @assembly: a dynamic assembly
4571 * @register_token: Whenever to register the token in the assembly->tokens hash.
4573 * Get a token to insert in the IL code stream for the given MemberInfo.
4574 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4575 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4579 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4580 gboolean create_methodspec, gboolean register_token)
4585 klass = obj->vtable->klass;
4586 if (strcmp (klass->name, "MethodBuilder") == 0) {
4587 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4588 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4590 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4591 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4593 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4594 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4595 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4596 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4597 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4599 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4600 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4602 token = mono_image_get_ctorbuilder_token (assembly, mb);
4603 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4604 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4605 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4606 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4607 if (tb->generic_params) {
4608 token = mono_image_get_generic_field_token (assembly, fb);
4610 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4612 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4613 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4614 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4615 } else if (strcmp (klass->name, "MonoType") == 0) {
4616 MonoReflectionType *tb = (MonoReflectionType *)obj;
4617 MonoClass *mc = mono_class_from_mono_type (tb->type);
4618 token = mono_metadata_token_from_dor (
4619 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4620 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4621 MonoReflectionType *tb = (MonoReflectionType *)obj;
4622 token = mono_metadata_token_from_dor (
4623 mono_image_typedef_or_ref (assembly, tb->type));
4624 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4625 MonoReflectionType *tb = (MonoReflectionType *)obj;
4626 token = mono_metadata_token_from_dor (
4627 mono_image_typedef_or_ref (assembly, tb->type));
4628 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4629 strcmp (klass->name, "MonoMethod") == 0 ||
4630 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4631 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4632 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4633 if (m->method->is_inflated) {
4634 if (create_methodspec)
4635 token = mono_image_get_methodspec_token (assembly, m->method);
4637 token = mono_image_get_inflated_method_token (assembly, m->method);
4638 } else if ((m->method->klass->image == &assembly->image) &&
4639 !m->method->klass->generic_class) {
4640 static guint32 method_table_idx = 0xffffff;
4641 if (m->method->klass->wastypebuilder) {
4642 /* we use the same token as the one that was assigned
4643 * to the Methodbuilder.
4644 * FIXME: do the equivalent for Fields.
4646 token = m->method->token;
4649 * Each token should have a unique index, but the indexes are
4650 * assigned by managed code, so we don't know about them. An
4651 * easy solution is to count backwards...
4653 method_table_idx --;
4654 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4657 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4659 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4660 } else if (strcmp (klass->name, "MonoField") == 0) {
4661 MonoReflectionField *f = (MonoReflectionField *)obj;
4662 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4663 static guint32 field_table_idx = 0xffffff;
4665 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4667 token = mono_image_get_fieldref_token (assembly, f);
4669 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4670 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4671 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4672 token = mono_image_get_array_token (assembly, m);
4673 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4674 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4675 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4676 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4677 MonoReflectionType *tb = (MonoReflectionType *)obj;
4678 token = mono_metadata_token_from_dor (
4679 mono_image_typedef_or_ref (assembly, tb->type));
4680 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4681 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4682 token = mono_image_get_field_on_inst_token (assembly, f);
4683 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4684 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4685 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4686 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4687 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4688 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4690 g_error ("requested token for %s\n", klass->name);
4694 mono_image_register_token (assembly, token, obj);
4700 * mono_image_register_token:
4702 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4703 * the Module.ResolveXXXToken () methods to work.
4706 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4708 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4710 /* There could be multiple MethodInfo objects with the same token */
4711 //g_assert (prev == obj);
4713 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4717 #endif /* DISABLE_REFLECTION_EMIT */
4720 guint32 import_lookup_table;
4724 guint32 import_address_table_rva;
4732 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4734 static MonoDynamicImage*
4735 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4737 static const guchar entrycode [16] = {0xff, 0x25, 0};
4738 MonoDynamicImage *image;
4741 const char *version;
4743 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4744 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4746 version = mono_get_runtime_info ()->runtime_version;
4749 image = GC_MALLOC (sizeof (MonoDynamicImage));
4751 image = g_new0 (MonoDynamicImage, 1);
4754 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4756 /*g_print ("created image %p\n", image);*/
4757 /* keep in sync with image.c */
4758 image->image.name = assembly_name;
4759 image->image.assembly_name = image->image.name; /* they may be different */
4760 image->image.module_name = module_name;
4761 image->image.version = g_strdup (version);
4762 image->image.md_version_major = 1;
4763 image->image.md_version_minor = 1;
4764 image->image.dynamic = TRUE;
4766 image->image.references = g_new0 (MonoAssembly*, 1);
4767 image->image.references [0] = NULL;
4769 mono_image_init (&image->image);
4771 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4772 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4773 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4774 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4775 image->handleref = g_hash_table_new (NULL, NULL);
4776 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4777 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4778 image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4779 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4780 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4781 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4782 image->gen_params = g_ptr_array_new ();
4784 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4785 string_heap_init (&image->sheap);
4786 mono_image_add_stream_data (&image->us, "", 1);
4787 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4788 /* import tables... */
4789 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4790 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4791 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4792 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4793 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4794 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4795 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4796 stream_data_align (&image->code);
4798 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4800 for (i=0; i < MONO_TABLE_NUM; ++i) {
4801 image->tables [i].next_idx = 1;
4802 image->tables [i].columns = table_sizes [i];
4805 image->image.assembly = (MonoAssembly*)assembly;
4806 image->run = assembly->run;
4807 image->save = assembly->save;
4808 image->pe_kind = 0x1; /* ILOnly */
4809 image->machine = 0x14c; /* I386 */
4811 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4817 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4823 mono_dynamic_image_free (MonoDynamicImage *image)
4825 MonoDynamicImage *di = image;
4830 mono_g_hash_table_destroy (di->methodspec);
4832 g_hash_table_destroy (di->typespec);
4834 g_hash_table_destroy (di->typeref);
4836 g_hash_table_destroy (di->handleref);
4838 mono_g_hash_table_destroy (di->tokens);
4839 if (di->generic_def_objects)
4840 mono_g_hash_table_destroy (di->generic_def_objects);
4841 if (di->blob_cache) {
4842 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4843 g_hash_table_destroy (di->blob_cache);
4845 if (di->standalonesig_cache)
4846 g_hash_table_destroy (di->standalonesig_cache);
4847 for (list = di->array_methods; list; list = list->next) {
4848 ArrayMethod *am = (ArrayMethod *)list->data;
4853 g_list_free (di->array_methods);
4854 if (di->gen_params) {
4855 for (i = 0; i < di->gen_params->len; i++) {
4856 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4857 if (entry->gparam->type.type) {
4858 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4859 g_free ((char*)param->name);
4861 g_free (entry->gparam->type.type);
4865 g_ptr_array_free (di->gen_params, TRUE);
4867 if (di->token_fixups)
4868 mono_g_hash_table_destroy (di->token_fixups);
4869 if (di->method_to_table_idx)
4870 g_hash_table_destroy (di->method_to_table_idx);
4871 if (di->field_to_table_idx)
4872 g_hash_table_destroy (di->field_to_table_idx);
4873 if (di->method_aux_hash)
4874 g_hash_table_destroy (di->method_aux_hash);
4875 g_free (di->strong_name);
4876 g_free (di->win32_res);
4878 g_free (di->public_key);
4880 /*g_print ("string heap destroy for image %p\n", di);*/
4881 mono_dynamic_stream_reset (&di->sheap);
4882 mono_dynamic_stream_reset (&di->code);
4883 mono_dynamic_stream_reset (&di->resources);
4884 mono_dynamic_stream_reset (&di->us);
4885 mono_dynamic_stream_reset (&di->blob);
4886 mono_dynamic_stream_reset (&di->tstream);
4887 mono_dynamic_stream_reset (&di->guid);
4888 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4889 g_free (di->tables [i].values);
4893 #ifndef DISABLE_REFLECTION_EMIT
4896 * mono_image_basic_init:
4897 * @assembly: an assembly builder object
4899 * Create the MonoImage that represents the assembly builder and setup some
4900 * of the helper hash table and the basic metadata streams.
4903 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4905 MonoDynamicAssembly *assembly;
4906 MonoDynamicImage *image;
4907 MonoDomain *domain = mono_object_domain (assemblyb);
4909 MONO_ARCH_SAVE_REGS;
4911 if (assemblyb->dynamic_assembly)
4915 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4917 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4920 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4922 assembly->assembly.ref_count = 1;
4923 assembly->assembly.dynamic = TRUE;
4924 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4925 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4926 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4927 if (assemblyb->culture)
4928 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4930 assembly->assembly.aname.culture = g_strdup ("");
4932 if (assemblyb->version) {
4933 char *vstr = mono_string_to_utf8 (assemblyb->version);
4934 char **version = g_strsplit (vstr, ".", 4);
4935 char **parts = version;
4936 assembly->assembly.aname.major = atoi (*parts++);
4937 assembly->assembly.aname.minor = atoi (*parts++);
4938 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4939 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4941 g_strfreev (version);
4944 assembly->assembly.aname.major = 0;
4945 assembly->assembly.aname.minor = 0;
4946 assembly->assembly.aname.build = 0;
4947 assembly->assembly.aname.revision = 0;
4950 assembly->run = assemblyb->access != 2;
4951 assembly->save = assemblyb->access != 1;
4953 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4954 image->initial_image = TRUE;
4955 assembly->assembly.aname.name = image->image.name;
4956 assembly->assembly.image = &image->image;
4958 mono_domain_assemblies_lock (domain);
4959 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4960 mono_domain_assemblies_unlock (domain);
4962 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4964 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4966 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4969 #endif /* DISABLE_REFLECTION_EMIT */
4972 calc_section_size (MonoDynamicImage *assembly)
4976 /* alignment constraints */
4977 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4978 g_assert ((assembly->code.index % 4) == 0);
4979 assembly->meta_size += 3;
4980 assembly->meta_size &= ~3;
4981 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4982 g_assert ((assembly->resources.index % 4) == 0);
4984 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4985 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4988 if (assembly->win32_res) {
4989 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4991 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4992 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4996 assembly->sections [MONO_SECTION_RELOC].size = 12;
4997 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5007 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5011 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5013 ResTreeNode *t1 = (ResTreeNode*)a;
5014 ResTreeNode *t2 = (ResTreeNode*)b;
5016 return t1->id - t2->id;
5020 * resource_tree_create:
5022 * Organize the resources into a resource tree.
5024 static ResTreeNode *
5025 resource_tree_create (MonoArray *win32_resources)
5027 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5031 tree = g_new0 (ResTreeNode, 1);
5033 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5034 MonoReflectionWin32Resource *win32_res =
5035 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5039 /* FIXME: BUG: this stores managed references in unmanaged memory */
5040 lang_node = g_new0 (ResTreeNode, 1);
5041 lang_node->id = win32_res->lang_id;
5042 lang_node->win32_res = win32_res;
5044 /* Create type node if neccesary */
5046 for (l = tree->children; l; l = l->next)
5047 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5048 type_node = (ResTreeNode*)l->data;
5053 type_node = g_new0 (ResTreeNode, 1);
5054 type_node->id = win32_res->res_type;
5057 * The resource types have to be sorted otherwise
5058 * Windows Explorer can't display the version information.
5060 tree->children = g_slist_insert_sorted (tree->children,
5061 type_node, resource_tree_compare_by_id);
5064 /* Create res node if neccesary */
5066 for (l = type_node->children; l; l = l->next)
5067 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5068 res_node = (ResTreeNode*)l->data;
5073 res_node = g_new0 (ResTreeNode, 1);
5074 res_node->id = win32_res->res_id;
5075 type_node->children = g_slist_append (type_node->children, res_node);
5078 res_node->children = g_slist_append (res_node->children, lang_node);
5085 * resource_tree_encode:
5087 * Encode the resource tree into the format used in the PE file.
5090 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5093 MonoPEResourceDir dir;
5094 MonoPEResourceDirEntry dir_entry;
5095 MonoPEResourceDataEntry data_entry;
5097 guint32 res_id_entries;
5100 * For the format of the resource directory, see the article
5101 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5105 memset (&dir, 0, sizeof (dir));
5106 memset (&dir_entry, 0, sizeof (dir_entry));
5107 memset (&data_entry, 0, sizeof (data_entry));
5109 g_assert (sizeof (dir) == 16);
5110 g_assert (sizeof (dir_entry) == 8);
5111 g_assert (sizeof (data_entry) == 16);
5113 node->offset = p - begin;
5115 /* IMAGE_RESOURCE_DIRECTORY */
5116 res_id_entries = g_slist_length (node->children);
5117 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5119 memcpy (p, &dir, sizeof (dir));
5122 /* Reserve space for entries */
5124 p += sizeof (dir_entry) * res_id_entries;
5126 /* Write children */
5127 for (l = node->children; l; l = l->next) {
5128 ResTreeNode *child = (ResTreeNode*)l->data;
5130 if (child->win32_res) {
5133 child->offset = p - begin;
5135 /* IMAGE_RESOURCE_DATA_ENTRY */
5136 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5137 size = mono_array_length (child->win32_res->res_data);
5138 data_entry.rde_size = GUINT32_TO_LE (size);
5140 memcpy (p, &data_entry, sizeof (data_entry));
5141 p += sizeof (data_entry);
5143 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5146 resource_tree_encode (child, begin, p, &p);
5150 /* IMAGE_RESOURCE_ENTRY */
5151 for (l = node->children; l; l = l->next) {
5152 ResTreeNode *child = (ResTreeNode*)l->data;
5154 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5155 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5157 memcpy (entries, &dir_entry, sizeof (dir_entry));
5158 entries += sizeof (dir_entry);
5165 resource_tree_free (ResTreeNode * node)
5168 for (list = node->children; list; list = list->next)
5169 resource_tree_free ((ResTreeNode*)list->data);
5170 g_slist_free(node->children);
5175 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5180 MonoReflectionWin32Resource *win32_res;
5183 if (!assemblyb->win32_resources)
5187 * Resources are stored in a three level tree inside the PE file.
5188 * - level one contains a node for each type of resource
5189 * - level two contains a node for each resource
5190 * - level three contains a node for each instance of a resource for a
5191 * specific language.
5194 tree = resource_tree_create (assemblyb->win32_resources);
5196 /* Estimate the size of the encoded tree */
5198 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5199 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5200 size += mono_array_length (win32_res->res_data);
5202 /* Directory structure */
5203 size += mono_array_length (assemblyb->win32_resources) * 256;
5204 p = buf = g_malloc (size);
5206 resource_tree_encode (tree, p, p, &p);
5208 g_assert (p - buf <= size);
5210 assembly->win32_res = g_malloc (p - buf);
5211 assembly->win32_res_size = p - buf;
5212 memcpy (assembly->win32_res, buf, p - buf);
5215 resource_tree_free (tree);
5219 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5221 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5224 p += sizeof (MonoPEResourceDir);
5225 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5226 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5227 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5228 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5229 fixup_resource_directory (res_section, child, rva);
5231 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5232 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5235 p += sizeof (MonoPEResourceDirEntry);
5240 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5243 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5244 g_error ("WriteFile returned %d\n", GetLastError ());
5247 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5250 * mono_image_create_pefile:
5251 * @mb: a module builder object
5253 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5254 * assembly->pefile where it can be easily retrieved later in chunks.
5257 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5259 MonoMSDOSHeader *msdos;
5260 MonoDotNetHeader *header;
5261 MonoSectionTable *section;
5262 MonoCLIHeader *cli_header;
5263 guint32 size, image_size, virtual_base, text_offset;
5264 guint32 header_start, section_start, file_offset, virtual_offset;
5265 MonoDynamicImage *assembly;
5266 MonoReflectionAssemblyBuilder *assemblyb;
5267 MonoDynamicStream pefile_stream = {0};
5268 MonoDynamicStream *pefile = &pefile_stream;
5270 guint32 *rva, value;
5272 static const unsigned char msheader[] = {
5273 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5274 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5277 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5278 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5279 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5280 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5283 assemblyb = mb->assemblyb;
5285 mono_image_basic_init (assemblyb);
5286 assembly = mb->dynamic_image;
5288 assembly->pe_kind = assemblyb->pe_kind;
5289 assembly->machine = assemblyb->machine;
5290 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5291 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5293 mono_image_build_metadata (mb);
5295 if (mb->is_main && assemblyb->resources) {
5296 int len = mono_array_length (assemblyb->resources);
5297 for (i = 0; i < len; ++i)
5298 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5301 if (mb->resources) {
5302 int len = mono_array_length (mb->resources);
5303 for (i = 0; i < len; ++i)
5304 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5307 build_compressed_metadata (assembly);
5310 assembly_add_win32_resources (assembly, assemblyb);
5312 nsections = calc_section_size (assembly);
5314 /* The DOS header and stub */
5315 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5316 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5318 /* the dotnet header */
5319 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5321 /* the section tables */
5322 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5324 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5325 virtual_offset = VIRT_ALIGN;
5328 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5329 if (!assembly->sections [i].size)
5332 file_offset += FILE_ALIGN - 1;
5333 file_offset &= ~(FILE_ALIGN - 1);
5334 virtual_offset += VIRT_ALIGN - 1;
5335 virtual_offset &= ~(VIRT_ALIGN - 1);
5337 assembly->sections [i].offset = file_offset;
5338 assembly->sections [i].rva = virtual_offset;
5340 file_offset += assembly->sections [i].size;
5341 virtual_offset += assembly->sections [i].size;
5342 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5345 file_offset += FILE_ALIGN - 1;
5346 file_offset &= ~(FILE_ALIGN - 1);
5348 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5350 /* back-patch info */
5351 msdos = (MonoMSDOSHeader*)pefile->data;
5352 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5354 header = (MonoDotNetHeader*)(pefile->data + header_start);
5355 header->pesig [0] = 'P';
5356 header->pesig [1] = 'E';
5358 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5359 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5360 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5361 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5362 if (assemblyb->pekind == 1) {
5364 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5367 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5370 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5372 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5373 header->pe.pe_major = 6;
5374 header->pe.pe_minor = 0;
5375 size = assembly->sections [MONO_SECTION_TEXT].size;
5376 size += FILE_ALIGN - 1;
5377 size &= ~(FILE_ALIGN - 1);
5378 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5379 size = assembly->sections [MONO_SECTION_RSRC].size;
5380 size += FILE_ALIGN - 1;
5381 size &= ~(FILE_ALIGN - 1);
5382 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5383 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5384 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5385 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5386 /* pe_rva_entry_point always at the beginning of the text section */
5387 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5389 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5390 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5391 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5392 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5393 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5394 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5395 size = section_start;
5396 size += FILE_ALIGN - 1;
5397 size &= ~(FILE_ALIGN - 1);
5398 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5400 size += VIRT_ALIGN - 1;
5401 size &= ~(VIRT_ALIGN - 1);
5402 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5405 // Translate the PEFileKind value to the value expected by the Windows loader
5411 // PEFileKinds.Dll == 1
5412 // PEFileKinds.ConsoleApplication == 2
5413 // PEFileKinds.WindowApplication == 3
5416 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5417 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5419 if (assemblyb->pekind == 3)
5424 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5426 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5427 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5428 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5429 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5430 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5431 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5433 /* fill data directory entries */
5435 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5436 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5438 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5439 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5441 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5442 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5443 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5444 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5445 /* patch entrypoint name */
5446 if (assemblyb->pekind == 1)
5447 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5449 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5450 /* patch imported function RVA name */
5451 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5452 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5454 /* the import table */
5455 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5456 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5457 /* patch imported dll RVA name and other entries in the dir */
5458 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5459 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5460 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5461 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5462 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5463 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5465 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5466 value = (assembly->text_rva + assembly->imp_names_offset);
5467 *p++ = (value) & 0xff;
5468 *p++ = (value >> 8) & (0xff);
5469 *p++ = (value >> 16) & (0xff);
5470 *p++ = (value >> 24) & (0xff);
5472 /* the CLI header info */
5473 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5474 cli_header->ch_size = GUINT32_FROM_LE (72);
5475 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5476 if (mono_framework_version () > 1)
5477 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5479 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5480 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5481 if (assemblyb->entry_point) {
5482 guint32 table_idx = 0;
5483 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5484 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5485 table_idx = methodb->table_idx;
5487 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5489 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5491 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5493 /* The embedded managed resources */
5494 text_offset = assembly->text_rva + assembly->code.index;
5495 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5496 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5497 text_offset += assembly->resources.index;
5498 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5499 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5500 text_offset += assembly->meta_size;
5501 if (assembly->strong_name_size) {
5502 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5503 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5504 text_offset += assembly->strong_name_size;
5507 /* write the section tables and section content */
5508 section = (MonoSectionTable*)(pefile->data + section_start);
5509 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5510 static const char section_names [][7] = {
5511 ".text", ".rsrc", ".reloc"
5513 if (!assembly->sections [i].size)
5515 strcpy (section->st_name, section_names [i]);
5516 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5517 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5518 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5519 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5520 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5521 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5522 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5526 checked_write_file (file, pefile->data, pefile->index);
5528 mono_dynamic_stream_reset (pefile);
5530 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5531 if (!assembly->sections [i].size)
5534 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5535 g_error ("SetFilePointer returned %d\n", GetLastError ());
5538 case MONO_SECTION_TEXT:
5539 /* patch entry point */
5540 p = (guchar*)(assembly->code.data + 2);
5541 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5542 *p++ = (value) & 0xff;
5543 *p++ = (value >> 8) & 0xff;
5544 *p++ = (value >> 16) & 0xff;
5545 *p++ = (value >> 24) & 0xff;
5547 checked_write_file (file, assembly->code.data, assembly->code.index);
5548 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5549 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5550 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5553 g_free (assembly->image.raw_metadata);
5555 case MONO_SECTION_RELOC: {
5559 guint16 type_and_offset;
5563 g_assert (sizeof (reloc) == 12);
5565 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5566 reloc.block_size = GUINT32_FROM_LE (12);
5569 * the entrypoint is always at the start of the text section
5570 * 3 is IMAGE_REL_BASED_HIGHLOW
5571 * 2 is patch_size_rva - text_rva
5573 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5576 checked_write_file (file, &reloc, sizeof (reloc));
5580 case MONO_SECTION_RSRC:
5581 if (assembly->win32_res) {
5583 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5584 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5585 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5589 g_assert_not_reached ();
5593 /* check that the file is properly padded */
5594 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5595 g_error ("SetFilePointer returned %d\n", GetLastError ());
5596 if (! SetEndOfFile (file))
5597 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5599 mono_dynamic_stream_reset (&assembly->code);
5600 mono_dynamic_stream_reset (&assembly->us);
5601 mono_dynamic_stream_reset (&assembly->blob);
5602 mono_dynamic_stream_reset (&assembly->guid);
5603 mono_dynamic_stream_reset (&assembly->sheap);
5605 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5606 g_hash_table_destroy (assembly->blob_cache);
5607 assembly->blob_cache = NULL;
5610 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5613 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5615 g_assert_not_reached ();
5618 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5620 #ifndef DISABLE_REFLECTION_EMIT
5622 MonoReflectionModule *
5623 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5627 MonoImageOpenStatus status;
5628 MonoDynamicAssembly *assembly;
5629 guint32 module_count;
5630 MonoImage **new_modules;
5631 gboolean *new_modules_loaded;
5633 name = mono_string_to_utf8 (fileName);
5635 image = mono_image_open (name, &status);
5638 if (status == MONO_IMAGE_ERROR_ERRNO)
5639 exc = mono_get_exception_file_not_found (fileName);
5641 exc = mono_get_exception_bad_image_format (name);
5643 mono_raise_exception (exc);
5648 assembly = ab->dynamic_assembly;
5649 image->assembly = (MonoAssembly*)assembly;
5651 module_count = image->assembly->image->module_count;
5652 new_modules = g_new0 (MonoImage *, module_count + 1);
5653 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5655 if (image->assembly->image->modules)
5656 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5657 if (image->assembly->image->modules_loaded)
5658 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5659 new_modules [module_count] = image;
5660 new_modules_loaded [module_count] = TRUE;
5661 mono_image_addref (image);
5663 g_free (image->assembly->image->modules);
5664 image->assembly->image->modules = new_modules;
5665 image->assembly->image->modules_loaded = new_modules_loaded;
5666 image->assembly->image->module_count ++;
5668 mono_assembly_load_references (image, &status);
5670 mono_image_close (image);
5671 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5674 return mono_module_get_object (mono_domain_get (), image);
5677 #endif /* DISABLE_REFLECTION_EMIT */
5680 * We need to return always the same object for MethodInfo, FieldInfo etc..
5681 * but we need to consider the reflected type.
5682 * type uses a different hash, since it uses custom hash/equal functions.
5687 MonoClass *refclass;
5691 reflected_equal (gconstpointer a, gconstpointer b) {
5692 const ReflectedEntry *ea = a;
5693 const ReflectedEntry *eb = b;
5695 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5699 reflected_hash (gconstpointer a) {
5700 const ReflectedEntry *ea = a;
5701 return mono_aligned_addr_hash (ea->item);
5704 #define CHECK_OBJECT(t,p,k) \
5710 mono_domain_lock (domain); \
5711 if (!domain->refobject_hash) \
5712 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5713 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5714 mono_domain_unlock (domain); \
5717 mono_domain_unlock (domain); \
5720 #ifdef HAVE_BOEHM_GC
5721 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5723 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5726 #define CACHE_OBJECT(t,p,o,k) \
5729 ReflectedEntry pe; \
5731 pe.refclass = (k); \
5732 mono_domain_lock (domain); \
5733 if (!domain->refobject_hash) \
5734 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5735 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5737 ReflectedEntry *e = ALLOC_REFENTRY; \
5739 e->refclass = (k); \
5740 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5743 mono_domain_unlock (domain); \
5748 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5750 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5754 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5756 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5759 #ifndef DISABLE_REFLECTION_EMIT
5762 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5764 MonoDynamicImage *image = moduleb->dynamic_image;
5765 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5768 MonoImage **new_modules;
5771 * FIXME: we already created an image in mono_image_basic_init (), but
5772 * we don't know which module it belongs to, since that is only
5773 * determined at assembly save time.
5775 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5776 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5778 moduleb->module.image = &image->image;
5779 moduleb->dynamic_image = image;
5780 register_module (mono_object_domain (moduleb), moduleb, image);
5782 /* register the module with the assembly */
5783 ass = ab->dynamic_assembly->assembly.image;
5784 module_count = ass->module_count;
5785 new_modules = g_new0 (MonoImage *, module_count + 1);
5788 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5789 new_modules [module_count] = &image->image;
5790 mono_image_addref (&image->image);
5792 g_free (ass->modules);
5793 ass->modules = new_modules;
5794 ass->module_count ++;
5801 * mono_assembly_get_object:
5802 * @domain: an app domain
5803 * @assembly: an assembly
5805 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5807 MonoReflectionAssembly*
5808 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5810 static MonoClass *System_Reflection_Assembly;
5811 MonoReflectionAssembly *res;
5813 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5814 if (!System_Reflection_Assembly)
5815 System_Reflection_Assembly = mono_class_from_name (
5816 mono_defaults.corlib, "System.Reflection", "Assembly");
5817 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5818 res->assembly = assembly;
5820 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5825 MonoReflectionModule*
5826 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5828 static MonoClass *System_Reflection_Module;
5829 MonoReflectionModule *res;
5832 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5833 if (!System_Reflection_Module)
5834 System_Reflection_Module = mono_class_from_name (
5835 mono_defaults.corlib, "System.Reflection", "Module");
5836 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5839 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5841 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5842 basename = g_path_get_basename (image->name);
5843 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5844 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5848 if (image->assembly->image == image) {
5849 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5853 if (image->assembly->image->modules) {
5854 for (i = 0; i < image->assembly->image->module_count; i++) {
5855 if (image->assembly->image->modules [i] == image)
5856 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5858 g_assert (res->token);
5862 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5865 MonoReflectionModule*
5866 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5868 static MonoClass *System_Reflection_Module;
5869 MonoReflectionModule *res;
5870 MonoTableInfo *table;
5871 guint32 cols [MONO_FILE_SIZE];
5873 guint32 i, name_idx;
5876 if (!System_Reflection_Module)
5877 System_Reflection_Module = mono_class_from_name (
5878 mono_defaults.corlib, "System.Reflection", "Module");
5879 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5881 table = &image->tables [MONO_TABLE_FILE];
5882 g_assert (table_index < table->rows);
5883 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5886 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5887 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5889 /* Check whenever the row has a corresponding row in the moduleref table */
5890 table = &image->tables [MONO_TABLE_MODULEREF];
5891 for (i = 0; i < table->rows; ++i) {
5892 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5893 val = mono_metadata_string_heap (image, name_idx);
5894 if (strcmp (val, name) == 0)
5895 res->image = image->modules [i];
5898 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5899 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5900 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5901 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5902 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5908 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5910 if ((t1->type != t2->type) ||
5911 (t1->byref != t2->byref))
5915 case MONO_TYPE_VOID:
5916 case MONO_TYPE_BOOLEAN:
5917 case MONO_TYPE_CHAR:
5928 case MONO_TYPE_STRING:
5931 case MONO_TYPE_OBJECT:
5932 case MONO_TYPE_TYPEDBYREF:
5934 case MONO_TYPE_VALUETYPE:
5935 case MONO_TYPE_CLASS:
5936 case MONO_TYPE_SZARRAY:
5937 return t1->data.klass == t2->data.klass;
5939 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5940 case MONO_TYPE_ARRAY:
5941 if (t1->data.array->rank != t2->data.array->rank)
5943 return t1->data.array->eklass == t2->data.array->eklass;
5944 case MONO_TYPE_GENERICINST: {
5946 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5947 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5948 if (i1->type_argc != i2->type_argc)
5950 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5951 &t2->data.generic_class->container_class->byval_arg))
5953 /* FIXME: we should probably just compare the instance pointers directly. */
5954 for (i = 0; i < i1->type_argc; ++i) {
5955 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5961 case MONO_TYPE_MVAR:
5962 return t1->data.generic_param == t2->data.generic_param;
5964 g_error ("implement type compare for %0x!", t1->type);
5972 mymono_metadata_type_hash (MonoType *t1)
5978 hash |= t1->byref << 6; /* do not collide with t1->type values */
5980 case MONO_TYPE_VALUETYPE:
5981 case MONO_TYPE_CLASS:
5982 case MONO_TYPE_SZARRAY:
5983 /* check if the distribution is good enough */
5984 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5986 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5987 case MONO_TYPE_GENERICINST: {
5989 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5990 hash += g_str_hash (t1->data.generic_class->container_class->name);
5992 for (i = 0; i < inst->type_argc; ++i) {
5993 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6002 static MonoReflectionGenericClass*
6003 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6005 static MonoClass *System_Reflection_MonoGenericClass;
6006 MonoReflectionGenericClass *res;
6007 MonoClass *klass, *gklass;
6009 if (!System_Reflection_MonoGenericClass) {
6010 System_Reflection_MonoGenericClass = mono_class_from_name (
6011 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6012 g_assert (System_Reflection_MonoGenericClass);
6015 klass = mono_class_from_mono_type (geninst);
6016 gklass = klass->generic_class->container_class;
6018 mono_class_init (klass);
6021 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6023 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6026 res->type.type = geninst;
6027 g_assert (gklass->reflection_info);
6028 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6029 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6035 verify_safe_for_managed_space (MonoType *type)
6037 switch (type->type) {
6039 case MONO_TYPE_ARRAY:
6040 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6042 return verify_safe_for_managed_space (type->data.type);
6043 case MONO_TYPE_SZARRAY:
6044 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6045 case MONO_TYPE_GENERICINST: {
6046 MonoGenericInst *inst = type->data.generic_class->inst;
6050 for (i = 0; i < inst->type_argc; ++i)
6051 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6057 case MONO_TYPE_MVAR:
6064 * mono_type_get_object:
6065 * @domain: an app domain
6068 * Return an System.MonoType object representing the type @type.
6071 mono_type_get_object (MonoDomain *domain, MonoType *type)
6073 MonoReflectionType *res;
6074 MonoClass *klass = mono_class_from_mono_type (type);
6076 /*we must avoid using @type as it might have come
6077 * from a mono_metadata_type_dup and the caller
6078 * expects that is can be freed.
6079 * Using the right type from
6081 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6083 /* void is very common */
6084 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6085 return (MonoReflectionType*)domain->typeof_void;
6088 * If the vtable of the given class was already created, we can use
6089 * the MonoType from there and avoid all locking and hash table lookups.
6091 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6092 * that the resulting object is diferent.
6094 if (type == &klass->byval_arg && !klass->image->dynamic) {
6095 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6096 if (vtable && vtable->type)
6097 return vtable->type;
6100 mono_domain_lock (domain);
6101 if (!domain->type_hash)
6102 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6103 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6104 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6105 mono_domain_unlock (domain);
6108 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6109 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6110 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6111 mono_g_hash_table_insert (domain->type_hash, type, res);
6112 mono_domain_unlock (domain);
6116 if (!verify_safe_for_managed_space (type)) {
6117 mono_domain_unlock (domain);
6118 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6121 if (klass->reflection_info && !klass->wastypebuilder) {
6122 /* g_assert_not_reached (); */
6123 /* should this be considered an error condition? */
6125 mono_domain_unlock (domain);
6126 return klass->reflection_info;
6129 // FIXME: Get rid of this, do it in the icalls for Type
6130 mono_class_init (klass);
6132 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6134 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6137 mono_g_hash_table_insert (domain->type_hash, type, res);
6139 if (type->type == MONO_TYPE_VOID)
6140 MONO_OBJECT_SETREF (domain, typeof_void, res);
6142 mono_domain_unlock (domain);
6147 * mono_method_get_object:
6148 * @domain: an app domain
6150 * @refclass: the reflected type (can be NULL)
6152 * Return an System.Reflection.MonoMethod object representing the method @method.
6154 MonoReflectionMethod*
6155 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6158 * We use the same C representation for methods and constructors, but the type
6159 * name in C# is different.
6161 static MonoClass *System_Reflection_MonoMethod = NULL;
6162 static MonoClass *System_Reflection_MonoCMethod = NULL;
6163 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6164 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6166 MonoReflectionMethod *ret;
6169 * Don't let static RGCTX invoke wrappers get into
6170 * MonoReflectionMethods.
6172 if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
6173 method = mono_marshal_method_from_wrapper (method);
6175 if (method->is_inflated) {
6176 MonoReflectionGenericMethod *gret;
6178 refclass = method->klass;
6179 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6180 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6181 if (!System_Reflection_MonoGenericCMethod)
6182 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6183 klass = System_Reflection_MonoGenericCMethod;
6185 if (!System_Reflection_MonoGenericMethod)
6186 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6187 klass = System_Reflection_MonoGenericMethod;
6189 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6190 gret->method.method = method;
6191 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6192 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6193 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6197 refclass = method->klass;
6199 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6200 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6201 if (!System_Reflection_MonoCMethod)
6202 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6203 klass = System_Reflection_MonoCMethod;
6206 if (!System_Reflection_MonoMethod)
6207 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6208 klass = System_Reflection_MonoMethod;
6210 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6211 ret->method = method;
6212 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6213 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6217 * mono_field_get_object:
6218 * @domain: an app domain
6222 * Return an System.Reflection.MonoField object representing the field @field
6225 MonoReflectionField*
6226 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6228 MonoReflectionField *res;
6229 static MonoClass *monofield_klass;
6231 CHECK_OBJECT (MonoReflectionField *, field, klass);
6232 if (!monofield_klass)
6233 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6234 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6237 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6238 if (is_field_on_inst (field))
6239 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6241 res->attrs = field->type->attrs;
6242 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6243 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6247 * mono_property_get_object:
6248 * @domain: an app domain
6250 * @property: a property
6252 * Return an System.Reflection.MonoProperty object representing the property @property
6255 MonoReflectionProperty*
6256 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6258 MonoReflectionProperty *res;
6259 static MonoClass *monoproperty_klass;
6261 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6262 if (!monoproperty_klass)
6263 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6264 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6266 res->property = property;
6267 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6271 * mono_event_get_object:
6272 * @domain: an app domain
6276 * Return an System.Reflection.MonoEvent object representing the event @event
6279 MonoReflectionEvent*
6280 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6282 MonoReflectionEvent *res;
6283 static MonoClass *monoevent_klass;
6285 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6286 if (!monoevent_klass)
6287 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6288 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6291 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6295 * mono_get_reflection_missing_object:
6296 * @domain: Domain where the object lives
6298 * Returns the System.Reflection.Missing.Value singleton object
6299 * (of type System.Reflection.Missing).
6301 * Used as the value for ParameterInfo.DefaultValue when Optional
6305 mono_get_reflection_missing_object (MonoDomain *domain)
6308 static MonoClassField *missing_value_field = NULL;
6310 if (!missing_value_field) {
6311 MonoClass *missing_klass;
6312 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6313 mono_class_init (missing_klass);
6314 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6315 g_assert (missing_value_field);
6317 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6323 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6326 *dbnull = mono_get_dbnull_object (domain);
6331 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6333 if (!*reflection_missing)
6334 *reflection_missing = mono_get_reflection_missing_object (domain);
6335 return *reflection_missing;
6339 * mono_param_get_objects:
6340 * @domain: an app domain
6343 * Return an System.Reflection.ParameterInfo array object representing the parameters
6344 * in the method @method.
6347 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6349 static MonoClass *System_Reflection_ParameterInfo;
6350 static MonoClass *System_Reflection_ParameterInfo_array;
6351 MonoArray *res = NULL;
6352 MonoReflectionMethod *member = NULL;
6353 MonoReflectionParameter *param = NULL;
6354 char **names, **blobs = NULL;
6355 guint32 *types = NULL;
6356 MonoType *type = NULL;
6357 MonoObject *dbnull = NULL;
6358 MonoObject *missing = NULL;
6359 MonoMarshalSpec **mspecs;
6360 MonoMethodSignature *sig;
6361 MonoVTable *pinfo_vtable;
6364 if (!System_Reflection_ParameterInfo_array) {
6367 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6368 mono_memory_barrier ();
6369 System_Reflection_ParameterInfo = klass;
6371 klass = mono_array_class_get (klass, 1);
6372 mono_memory_barrier ();
6373 System_Reflection_ParameterInfo_array = klass;
6376 if (!mono_method_signature (method)->param_count)
6377 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6379 /* Note: the cache is based on the address of the signature into the method
6380 * since we already cache MethodInfos with the method as keys.
6382 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6384 sig = mono_method_signature (method);
6385 member = mono_method_get_object (domain, method, NULL);
6386 names = g_new (char *, sig->param_count);
6387 mono_method_get_param_names (method, (const char **) names);
6389 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6390 mono_method_get_marshal_info (method, mspecs);
6392 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6393 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6394 for (i = 0; i < sig->param_count; ++i) {
6395 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6396 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6397 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6398 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6399 param->PositionImpl = i;
6400 param->AttrsImpl = sig->params [i]->attrs;
6402 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6403 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6404 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6406 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6410 blobs = g_new0 (char *, sig->param_count);
6411 types = g_new0 (guint32, sig->param_count);
6412 get_default_param_value_blobs (method, blobs, types);
6415 /* Build MonoType for the type from the Constant Table */
6417 type = g_new0 (MonoType, 1);
6418 type->type = types [i];
6419 type->data.klass = NULL;
6420 if (types [i] == MONO_TYPE_CLASS)
6421 type->data.klass = mono_defaults.object_class;
6422 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6423 /* For enums, types [i] contains the base type */
6425 type->type = MONO_TYPE_VALUETYPE;
6426 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6428 type->data.klass = mono_class_from_mono_type (type);
6430 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6432 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6433 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6434 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6435 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6437 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6443 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6445 mono_array_setref (res, i, param);
6452 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6454 mono_metadata_free_marshal_spec (mspecs [i]);
6457 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6461 * mono_method_body_get_object:
6462 * @domain: an app domain
6465 * Return an System.Reflection.MethodBody object representing the method @method.
6467 MonoReflectionMethodBody*
6468 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6470 static MonoClass *System_Reflection_MethodBody = NULL;
6471 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6472 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6473 MonoReflectionMethodBody *ret;
6474 MonoMethodNormal *mn;
6475 MonoMethodHeader *header;
6476 guint32 method_rva, local_var_sig_token;
6478 unsigned char format, flags;
6481 if (!System_Reflection_MethodBody)
6482 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6483 if (!System_Reflection_LocalVariableInfo)
6484 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6485 if (!System_Reflection_ExceptionHandlingClause)
6486 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6488 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6490 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6491 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6492 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6493 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6495 mn = (MonoMethodNormal *)method;
6496 header = mono_method_get_header (method);
6498 /* Obtain local vars signature token */
6499 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6500 ptr = mono_image_rva_map (method->klass->image, method_rva);
6501 flags = *(const unsigned char *) ptr;
6502 format = flags & METHOD_HEADER_FORMAT_MASK;
6504 case METHOD_HEADER_TINY_FORMAT:
6505 case METHOD_HEADER_TINY_FORMAT1:
6506 local_var_sig_token = 0;
6508 case METHOD_HEADER_FAT_FORMAT:
6512 local_var_sig_token = read32 (ptr);
6515 g_assert_not_reached ();
6518 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6520 ret->init_locals = header->init_locals;
6521 ret->max_stack = header->max_stack;
6522 ret->local_var_sig_token = local_var_sig_token;
6523 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6524 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6527 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6528 for (i = 0; i < header->num_locals; ++i) {
6529 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6530 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6531 info->is_pinned = header->locals [i]->pinned;
6532 info->local_index = i;
6533 mono_array_setref (ret->locals, i, info);
6537 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6538 for (i = 0; i < header->num_clauses; ++i) {
6539 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6540 MonoExceptionClause *clause = &header->clauses [i];
6542 info->flags = clause->flags;
6543 info->try_offset = clause->try_offset;
6544 info->try_length = clause->try_len;
6545 info->handler_offset = clause->handler_offset;
6546 info->handler_length = clause->handler_len;
6547 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6548 info->filter_offset = clause->data.filter_offset;
6549 else if (clause->data.catch_class)
6550 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6552 mono_array_setref (ret->clauses, i, info);
6555 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6560 * mono_get_dbnull_object:
6561 * @domain: Domain where the object lives
6563 * Returns the System.DBNull.Value singleton object
6565 * Used as the value for ParameterInfo.DefaultValue
6568 mono_get_dbnull_object (MonoDomain *domain)
6571 static MonoClassField *dbnull_value_field = NULL;
6573 if (!dbnull_value_field) {
6574 MonoClass *dbnull_klass;
6575 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6576 mono_class_init (dbnull_klass);
6577 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6578 g_assert (dbnull_value_field);
6580 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6586 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6588 guint32 param_index, i, lastp, crow = 0;
6589 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6592 MonoClass *klass = method->klass;
6593 MonoImage *image = klass->image;
6594 MonoMethodSignature *methodsig = mono_method_signature (method);
6596 MonoTableInfo *constt;
6597 MonoTableInfo *methodt;
6598 MonoTableInfo *paramt;
6600 if (!methodsig->param_count)
6603 mono_class_init (klass);
6605 if (klass->image->dynamic) {
6606 MonoReflectionMethodAux *aux;
6607 if (method->is_inflated)
6608 method = ((MonoMethodInflated*)method)->declaring;
6609 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6610 if (aux && aux->param_defaults) {
6611 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6612 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6617 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6618 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6619 constt = &image->tables [MONO_TABLE_CONSTANT];
6621 idx = mono_method_get_index (method) - 1;
6622 g_assert (idx != -1);
6624 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6625 if (idx + 1 < methodt->rows)
6626 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6628 lastp = paramt->rows + 1;
6630 for (i = param_index; i < lastp; ++i) {
6633 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6634 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6636 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6639 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6644 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6645 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6646 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6653 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6658 MonoType *basetype = type;
6663 klass = mono_class_from_mono_type (type);
6664 if (klass->valuetype) {
6665 object = mono_object_new (domain, klass);
6666 retval = ((gchar *) object + sizeof (MonoObject));
6667 if (klass->enumtype)
6668 basetype = klass->enum_basetype;
6673 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6680 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6684 memset (assembly, 0, sizeof (MonoAssemblyName));
6686 assembly->culture = "";
6687 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6689 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6692 while (g_ascii_isspace (*p) || *p == ',') {
6701 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6703 assembly->major = strtoul (p, &s, 10);
6704 if (s == p || *s != '.')
6707 assembly->minor = strtoul (p, &s, 10);
6708 if (s == p || *s != '.')
6711 assembly->build = strtoul (p, &s, 10);
6712 if (s == p || *s != '.')
6715 assembly->revision = strtoul (p, &s, 10);
6719 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6721 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6722 assembly->culture = "";
6725 assembly->culture = p;
6726 while (*p && *p != ',') {
6730 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6732 if (strncmp (p, "null", 4) == 0) {
6737 while (*p && *p != ',') {
6740 len = (p - start + 1);
6741 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6742 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6743 g_strlcpy ((char*)assembly->public_key_token, start, len);
6746 while (*p && *p != ',')
6750 while (g_ascii_isspace (*p) || *p == ',') {
6764 * mono_reflection_parse_type:
6767 * Parse a type name as accepted by the GetType () method and output the info
6768 * extracted in the info structure.
6769 * the name param will be mangled, so, make a copy before passing it to this function.
6770 * The fields in info will be valid until the memory pointed to by name is valid.
6772 * See also mono_type_get_name () below.
6774 * Returns: 0 on parse error.
6777 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6778 MonoTypeNameParse *info)
6780 char *start, *p, *w, *temp, *last_point, *startn;
6781 int in_modifiers = 0;
6782 int isbyref = 0, rank, arity = 0, i;
6784 start = p = w = name;
6786 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6787 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6788 info->name = info->name_space = NULL;
6789 info->nested = NULL;
6790 info->modifiers = NULL;
6791 info->type_arguments = NULL;
6793 /* last_point separates the namespace from the name */
6796 while (*p == ' ') p++, start++, w++, name++;
6801 *p = 0; /* NULL terminate the name */
6803 info->nested = g_list_append (info->nested, startn);
6804 /* we have parsed the nesting namespace + name */
6808 info->name_space = start;
6810 info->name = last_point + 1;
6812 info->name_space = (char *)"";
6831 i = strtol (p, &temp, 10);
6848 info->name_space = start;
6850 info->name = last_point + 1;
6852 info->name_space = (char *)"";
6859 if (isbyref) /* only one level allowed by the spec */
6862 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6866 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6872 info->type_arguments = g_ptr_array_new ();
6873 for (i = 0; i < arity; i++) {
6874 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6875 gboolean fqname = FALSE;
6877 g_ptr_array_add (info->type_arguments, subinfo);
6884 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6895 while (*p && (*p != ']'))
6903 if (g_ascii_isspace (*aname)) {
6910 !assembly_name_to_aname (&subinfo->assembly, aname))
6914 if (i + 1 < arity) {
6934 else if (*p == '*') /* '*' means unknown lower bound */
6935 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6942 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6953 if (g_ascii_isspace (*p)) {
6960 return 0; /* missing assembly name */
6961 if (!assembly_name_to_aname (&info->assembly, p))
6967 if (info->assembly.name)
6970 // *w = 0; /* terminate class name */
6972 if (!info->name || !*info->name)
6976 /* add other consistency checks */
6981 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6983 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6987 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6989 gboolean type_resolve = FALSE;
6991 MonoImage *rootimage = image;
6993 if (info->assembly.name) {
6994 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6995 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
6997 * This could happen in the AOT compiler case when the search hook is not
7000 assembly = image->assembly;
7002 /* then we must load the assembly ourselve - see #60439 */
7003 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7007 image = assembly->image;
7008 } else if (!image) {
7009 image = mono_defaults.corlib;
7012 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7013 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7014 image = mono_defaults.corlib;
7015 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7022 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7027 gboolean bounded = FALSE;
7030 image = mono_defaults.corlib;
7033 klass = mono_class_from_name_case (image, info->name_space, info->name);
7035 klass = mono_class_from_name (image, info->name_space, info->name);
7038 for (mod = info->nested; mod; mod = mod->next) {
7039 gpointer iter = NULL;
7043 mono_class_init (parent);
7045 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7047 if (g_strcasecmp (klass->name, mod->data) == 0)
7050 if (strcmp (klass->name, mod->data) == 0)
7059 mono_class_init (klass);
7061 if (info->type_arguments) {
7062 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7063 MonoReflectionType *the_type;
7067 for (i = 0; i < info->type_arguments->len; i++) {
7068 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7070 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7071 if (!type_args [i]) {
7077 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7079 instance = mono_reflection_bind_generic_parameters (
7080 the_type, info->type_arguments->len, type_args);
7086 klass = mono_class_from_mono_type (instance);
7089 for (mod = info->modifiers; mod; mod = mod->next) {
7090 modval = GPOINTER_TO_UINT (mod->data);
7091 if (!modval) { /* byref: must be last modifier */
7092 return &klass->this_arg;
7093 } else if (modval == -1) {
7094 klass = mono_ptr_class_get (&klass->byval_arg);
7095 } else if (modval == -2) {
7097 } else { /* array rank */
7098 klass = mono_bounded_array_class_get (klass, modval, bounded);
7100 mono_class_init (klass);
7103 return &klass->byval_arg;
7107 * mono_reflection_get_type:
7108 * @image: a metadata context
7109 * @info: type description structure
7110 * @ignorecase: flag for case-insensitive string compares
7111 * @type_resolve: whenever type resolve was already tried
7113 * Build a MonoType from the type description in @info.
7118 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7119 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7123 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7125 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7129 g_assert (assembly->dynamic);
7131 /* Enumerate all modules */
7134 if (abuilder->modules) {
7135 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7136 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7137 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7143 if (!type && abuilder->loaded_modules) {
7144 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7145 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7146 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7156 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7159 MonoReflectionAssembly *assembly;
7163 if (image && image->dynamic)
7164 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7166 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7169 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7176 *type_resolve = TRUE;
7179 /* Reconstruct the type name */
7180 fullName = g_string_new ("");
7181 if (info->name_space && (info->name_space [0] != '\0'))
7182 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7184 g_string_printf (fullName, info->name);
7185 for (mod = info->nested; mod; mod = mod->next)
7186 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7188 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7190 if (assembly->assembly->dynamic)
7191 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7193 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7196 g_string_free (fullName, TRUE);
7201 mono_reflection_free_type_info (MonoTypeNameParse *info)
7203 g_list_free (info->modifiers);
7204 g_list_free (info->nested);
7206 if (info->type_arguments) {
7209 for (i = 0; i < info->type_arguments->len; i++) {
7210 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7212 mono_reflection_free_type_info (subinfo);
7213 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7217 g_ptr_array_free (info->type_arguments, TRUE);
7222 * mono_reflection_type_from_name:
7224 * @image: a metadata context (can be NULL).
7226 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7227 * it defaults to get the type from @image or, if @image is NULL or loading
7228 * from it fails, uses corlib.
7232 mono_reflection_type_from_name (char *name, MonoImage *image)
7234 MonoType *type = NULL;
7235 MonoTypeNameParse info;
7238 /* Make a copy since parse_type modifies its argument */
7239 tmp = g_strdup (name);
7241 /*g_print ("requested type %s\n", str);*/
7242 if (mono_reflection_parse_type (tmp, &info)) {
7243 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7247 mono_reflection_free_type_info (&info);
7252 * mono_reflection_get_token:
7254 * Return the metadata token of OBJ which should be an object
7255 * representing a metadata element.
7258 mono_reflection_get_token (MonoObject *obj)
7263 klass = obj->vtable->klass;
7265 if (strcmp (klass->name, "MethodBuilder") == 0) {
7266 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7268 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7269 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7270 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7272 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7273 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7274 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7276 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7277 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7278 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7279 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7280 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7281 } else if (strcmp (klass->name, "MonoType") == 0) {
7282 MonoReflectionType *tb = (MonoReflectionType *)obj;
7283 token = mono_class_from_mono_type (tb->type)->type_token;
7284 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7285 strcmp (klass->name, "MonoMethod") == 0 ||
7286 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7287 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7288 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7289 if (m->method->is_inflated) {
7290 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7291 return inflated->declaring->token;
7293 token = m->method->token;
7295 } else if (strcmp (klass->name, "MonoField") == 0) {
7296 MonoReflectionField *f = (MonoReflectionField*)obj;
7298 if (is_field_on_inst (f->field)) {
7299 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7300 int field_index = f->field - dgclass->fields;
7303 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7304 obj = dgclass->field_objects [field_index];
7305 return mono_reflection_get_token (obj);
7307 token = mono_class_get_field_token (f->field);
7308 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7309 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7311 token = mono_class_get_property_token (p->property);
7312 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7313 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7315 token = mono_class_get_event_token (p->event);
7316 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7317 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7319 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7320 } else if (strcmp (klass->name, "Module") == 0) {
7321 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7324 } else if (strcmp (klass->name, "Assembly") == 0) {
7325 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7327 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7328 MonoException *ex = mono_get_exception_not_implemented (msg);
7330 mono_raise_exception (ex);
7337 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7339 int slen, type = t->type;
7340 MonoClass *tklass = t->data.klass;
7346 case MONO_TYPE_BOOLEAN: {
7347 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7352 case MONO_TYPE_CHAR:
7354 case MONO_TYPE_I2: {
7355 guint16 *val = g_malloc (sizeof (guint16));
7360 #if SIZEOF_VOID_P == 4
7366 case MONO_TYPE_I4: {
7367 guint32 *val = g_malloc (sizeof (guint32));
7372 #if SIZEOF_VOID_P == 8
7373 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7377 case MONO_TYPE_I8: {
7378 guint64 *val = g_malloc (sizeof (guint64));
7383 case MONO_TYPE_R8: {
7384 double *val = g_malloc (sizeof (double));
7389 case MONO_TYPE_VALUETYPE:
7390 if (t->data.klass->enumtype) {
7391 type = t->data.klass->enum_basetype->type;
7394 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7397 case MONO_TYPE_STRING:
7398 if (*p == (char)0xFF) {
7402 slen = mono_metadata_decode_value (p, &p);
7404 return mono_string_new_len (mono_domain_get (), p, slen);
7405 case MONO_TYPE_CLASS: {
7408 if (*p == (char)0xFF) {
7413 slen = mono_metadata_decode_value (p, &p);
7414 n = g_memdup (p, slen + 1);
7416 t = mono_reflection_type_from_name (n, image);
7418 g_warning ("Cannot load type '%s'", n);
7422 return mono_type_get_object (mono_domain_get (), t);
7426 case MONO_TYPE_OBJECT: {
7429 MonoClass *subc = NULL;
7434 } else if (subt == 0x0E) {
7435 type = MONO_TYPE_STRING;
7437 } else if (subt == 0x1D) {
7438 MonoType simple_type = {{0}};
7443 /* See Partition II, Appendix B3 */
7444 etype = MONO_TYPE_OBJECT;
7445 type = MONO_TYPE_SZARRAY;
7446 simple_type.type = etype;
7447 tklass = mono_class_from_mono_type (&simple_type);
7449 } else if (subt == 0x55) {
7452 slen = mono_metadata_decode_value (p, &p);
7453 n = g_memdup (p, slen + 1);
7455 t = mono_reflection_type_from_name (n, image);
7457 g_error ("Cannot load type '%s'", n);
7460 subc = mono_class_from_mono_type (t);
7461 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7462 MonoType simple_type = {{0}};
7463 simple_type.type = subt;
7464 subc = mono_class_from_mono_type (&simple_type);
7466 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7468 val = load_cattr_value (image, &subc->byval_arg, p, end);
7469 obj = mono_object_new (mono_domain_get (), subc);
7470 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7474 case MONO_TYPE_SZARRAY: {
7476 guint32 i, alen, basetype;
7479 if (alen == 0xffffffff) {
7483 arr = mono_array_new (mono_domain_get(), tklass, alen);
7484 basetype = tklass->byval_arg.type;
7485 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7486 basetype = tklass->enum_basetype->type;
7491 case MONO_TYPE_BOOLEAN:
7492 for (i = 0; i < alen; i++) {
7493 MonoBoolean val = *p++;
7494 mono_array_set (arr, MonoBoolean, i, val);
7497 case MONO_TYPE_CHAR:
7500 for (i = 0; i < alen; i++) {
7501 guint16 val = read16 (p);
7502 mono_array_set (arr, guint16, i, val);
7509 for (i = 0; i < alen; i++) {
7510 guint32 val = read32 (p);
7511 mono_array_set (arr, guint32, i, val);
7516 for (i = 0; i < alen; i++) {
7519 mono_array_set (arr, double, i, val);
7525 for (i = 0; i < alen; i++) {
7526 guint64 val = read64 (p);
7527 mono_array_set (arr, guint64, i, val);
7531 case MONO_TYPE_CLASS:
7532 case MONO_TYPE_OBJECT:
7533 case MONO_TYPE_STRING:
7534 for (i = 0; i < alen; i++) {
7535 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7536 mono_array_setref (arr, i, item);
7540 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7546 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7552 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7554 static MonoClass *klass;
7555 static MonoMethod *ctor;
7557 void *params [2], *unboxed;
7560 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7562 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7564 params [0] = mono_type_get_object (mono_domain_get (), t);
7566 retval = mono_object_new (mono_domain_get (), klass);
7567 unboxed = mono_object_unbox (retval);
7568 mono_runtime_invoke (ctor, unboxed, params, NULL);
7574 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7576 static MonoClass *klass;
7577 static MonoMethod *ctor;
7579 void *unboxed, *params [2];
7582 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7584 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7587 params [1] = typedarg;
7588 retval = mono_object_new (mono_domain_get (), klass);
7589 unboxed = mono_object_unbox (retval);
7590 mono_runtime_invoke (ctor, unboxed, params, NULL);
7596 type_is_reference (MonoType *type)
7598 switch (type->type) {
7599 case MONO_TYPE_BOOLEAN:
7600 case MONO_TYPE_CHAR:
7613 case MONO_TYPE_VALUETYPE:
7621 free_param_data (MonoMethodSignature *sig, void **params) {
7623 for (i = 0; i < sig->param_count; ++i) {
7624 if (!type_is_reference (sig->params [i]))
7625 g_free (params [i]);
7630 * Find the field index in the metadata FieldDef table.
7633 find_field_index (MonoClass *klass, MonoClassField *field) {
7636 for (i = 0; i < klass->field.count; ++i) {
7637 if (field == &klass->fields [i])
7638 return klass->field.first + 1 + i;
7644 * Find the property index in the metadata Property table.
7647 find_property_index (MonoClass *klass, MonoProperty *property) {
7650 for (i = 0; i < klass->property.count; ++i) {
7651 if (property == &klass->properties [i])
7652 return klass->property.first + 1 + i;
7658 * Find the event index in the metadata Event table.
7661 find_event_index (MonoClass *klass, MonoEvent *event) {
7664 for (i = 0; i < klass->event.count; ++i) {
7665 if (event == &klass->events [i])
7666 return klass->event.first + 1 + i;
7672 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7674 const char *p = (const char*)data;
7676 guint32 i, j, num_named;
7680 mono_class_init (method->klass);
7683 attr = mono_object_new (mono_domain_get (), method->klass);
7684 mono_runtime_invoke (method, attr, NULL, NULL);
7688 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7691 /*g_print ("got attr %s\n", method->klass->name);*/
7693 /* Allocate using alloca so it gets GC tracking */
7694 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7698 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7699 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7703 attr = mono_object_new (mono_domain_get (), method->klass);
7704 mono_runtime_invoke (method, attr, params, NULL);
7705 free_param_data (method->signature, params);
7706 num_named = read16 (named);
7708 for (j = 0; j < num_named; j++) {
7710 char *name, named_type, data_type;
7711 named_type = *named++;
7712 data_type = *named++; /* type of data */
7713 if (data_type == MONO_TYPE_SZARRAY)
7714 data_type = *named++;
7715 if (data_type == MONO_TYPE_ENUM) {
7718 type_len = mono_metadata_decode_blob_size (named, &named);
7719 type_name = g_malloc (type_len + 1);
7720 memcpy (type_name, named, type_len);
7721 type_name [type_len] = 0;
7723 /* FIXME: lookup the type and check type consistency */
7726 name_len = mono_metadata_decode_blob_size (named, &named);
7727 name = g_malloc (name_len + 1);
7728 memcpy (name, named, name_len);
7729 name [name_len] = 0;
7731 if (named_type == 0x53) {
7732 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7733 void *val = load_cattr_value (image, field->type, named, &named);
7734 mono_field_set_value (attr, field, val);
7735 if (!type_is_reference (field->type))
7737 } else if (named_type == 0x54) {
7740 MonoType *prop_type;
7742 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7743 /* can we have more that 1 arg in a custom attr named property? */
7744 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7745 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7746 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7747 mono_property_set_value (prop, attr, pparams, NULL);
7748 if (!type_is_reference (prop_type))
7749 g_free (pparams [0]);
7758 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7760 MonoArray *typedargs, *namedargs;
7761 MonoClass *attrklass;
7762 static MonoMethod *ctor;
7765 const char *p = (const char*)data;
7767 guint32 i, j, num_named;
7770 mono_class_init (method->klass);
7773 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7775 domain = mono_domain_get ();
7777 /* This is for Attributes with no parameters */
7778 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7779 params [0] = mono_method_get_object (domain, method, NULL);
7780 params [1] = params [2] = NULL;
7781 mono_runtime_invoke (method, attr, params, NULL);
7785 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7788 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7792 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7793 MonoObject *obj, *typedarg;
7796 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7797 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7798 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7799 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7800 mono_array_setref (typedargs, i, typedarg);
7802 if (!type_is_reference (mono_method_signature (method)->params [i]))
7807 num_named = read16 (named);
7808 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7810 attrklass = method->klass;
7811 for (j = 0; j < num_named; j++) {
7813 char *name, named_type, data_type;
7814 named_type = *named++;
7815 data_type = *named++; /* type of data */
7816 if (data_type == MONO_TYPE_SZARRAY)
7817 data_type = *named++;
7818 if (data_type == MONO_TYPE_ENUM) {
7821 type_len = mono_metadata_decode_blob_size (named, &named);
7822 type_name = g_malloc (type_len + 1);
7823 memcpy (type_name, named, type_len);
7824 type_name [type_len] = 0;
7826 /* FIXME: lookup the type and check type consistency */
7829 name_len = mono_metadata_decode_blob_size (named, &named);
7830 name = g_malloc (name_len + 1);
7831 memcpy (name, named, name_len);
7832 name [name_len] = 0;
7834 if (named_type == 0x53) {
7835 MonoObject *obj, *typedarg, *namedarg;
7836 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7837 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7839 minfo = mono_field_get_object (domain, NULL, field);
7840 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7841 typedarg = create_cattr_typed_arg (field->type, obj);
7842 namedarg = create_cattr_named_arg (minfo, typedarg);
7843 mono_array_setref (namedargs, j, namedarg);
7844 if (!type_is_reference (field->type))
7846 } else if (named_type == 0x54) {
7847 MonoObject *obj, *typedarg, *namedarg;
7848 MonoType *prop_type;
7850 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7852 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7853 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7854 minfo = mono_property_get_object (domain, NULL, prop);
7855 val = load_cattr_value (image, prop_type, named, &named);
7856 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7857 typedarg = create_cattr_typed_arg (prop_type, obj);
7858 namedarg = create_cattr_named_arg (minfo, typedarg);
7859 mono_array_setref (namedargs, j, namedarg);
7860 if (!type_is_reference (prop_type))
7865 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7866 params [0] = mono_method_get_object (domain, method, NULL);
7867 params [1] = typedargs;
7868 params [2] = namedargs;
7869 mono_runtime_invoke (ctor, attr, params, NULL);
7874 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7880 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7881 for (i = 0; i < cinfo->num_attrs; ++i) {
7882 if (!cinfo->attrs [i].ctor)
7883 /* The cattr type is not finished yet */
7884 /* We should include the type name but cinfo doesn't contain it */
7885 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7886 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7887 mono_array_setref (result, i, attr);
7893 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7900 for (i = 0; i < cinfo->num_attrs; ++i) {
7901 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7905 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7907 for (i = 0; i < cinfo->num_attrs; ++i) {
7908 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7909 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7910 mono_array_setref (result, n, attr);
7918 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7924 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7925 for (i = 0; i < cinfo->num_attrs; ++i) {
7926 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7927 mono_array_setref (result, i, attr);
7933 * mono_custom_attrs_from_index:
7935 * Returns: NULL if no attributes are found or if a loading error occurs.
7938 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7940 guint32 mtoken, i, len;
7941 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7943 MonoCustomAttrInfo *ainfo;
7944 GList *tmp, *list = NULL;
7947 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7949 i = mono_metadata_custom_attrs_from_index (image, idx);
7953 while (i < ca->rows) {
7954 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7956 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7959 len = g_list_length (list);
7962 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7963 ainfo->num_attrs = len;
7964 ainfo->image = image;
7965 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7966 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7967 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7968 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7969 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7970 mtoken |= MONO_TOKEN_METHOD_DEF;
7972 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7973 mtoken |= MONO_TOKEN_MEMBER_REF;
7976 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7979 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7980 if (!ainfo->attrs [i].ctor) {
7981 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7986 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7987 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7988 ainfo->attrs [i].data = (guchar*)data;
7996 mono_custom_attrs_from_method (MonoMethod *method)
8001 * An instantiated method has the same cattrs as the generic method definition.
8003 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8004 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8006 if (method->is_inflated)
8007 method = ((MonoMethodInflated *) method)->declaring;
8009 if (method->dynamic || method->klass->image->dynamic)
8010 return lookup_custom_attr (method->klass->image, method);
8012 idx = mono_method_get_index (method);
8013 idx <<= MONO_CUSTOM_ATTR_BITS;
8014 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8015 return mono_custom_attrs_from_index (method->klass->image, idx);
8019 mono_custom_attrs_from_class (MonoClass *klass)
8023 if (klass->generic_class)
8024 klass = klass->generic_class->container_class;
8026 if (klass->image->dynamic)
8027 return lookup_custom_attr (klass->image, klass);
8029 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8030 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8031 idx <<= MONO_CUSTOM_ATTR_BITS;
8032 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8034 idx = mono_metadata_token_index (klass->type_token);
8035 idx <<= MONO_CUSTOM_ATTR_BITS;
8036 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8038 return mono_custom_attrs_from_index (klass->image, idx);
8042 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8046 if (assembly->image->dynamic)
8047 return lookup_custom_attr (assembly->image, assembly);
8048 idx = 1; /* there is only one assembly */
8049 idx <<= MONO_CUSTOM_ATTR_BITS;
8050 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8051 return mono_custom_attrs_from_index (assembly->image, idx);
8054 static MonoCustomAttrInfo*
8055 mono_custom_attrs_from_module (MonoImage *image)
8060 return lookup_custom_attr (image, image);
8061 idx = 1; /* there is only one module */
8062 idx <<= MONO_CUSTOM_ATTR_BITS;
8063 idx |= MONO_CUSTOM_ATTR_MODULE;
8064 return mono_custom_attrs_from_index (image, idx);
8068 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8072 if (klass->image->dynamic) {
8073 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8074 return lookup_custom_attr (klass->image, property);
8076 idx = find_property_index (klass, property);
8077 idx <<= MONO_CUSTOM_ATTR_BITS;
8078 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8079 return mono_custom_attrs_from_index (klass->image, idx);
8083 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8087 if (klass->image->dynamic) {
8088 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8089 return lookup_custom_attr (klass->image, event);
8091 idx = find_event_index (klass, event);
8092 idx <<= MONO_CUSTOM_ATTR_BITS;
8093 idx |= MONO_CUSTOM_ATTR_EVENT;
8094 return mono_custom_attrs_from_index (klass->image, idx);
8098 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8101 if (klass->image->dynamic) {
8102 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8103 return lookup_custom_attr (klass->image, field);
8105 idx = find_field_index (klass, field);
8106 idx <<= MONO_CUSTOM_ATTR_BITS;
8107 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8108 return mono_custom_attrs_from_index (klass->image, idx);
8112 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8115 guint32 i, idx, method_index;
8116 guint32 param_list, param_last, param_pos, found;
8118 MonoReflectionMethodAux *aux;
8121 * An instantiated method has the same cattrs as the generic method definition.
8123 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8124 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8126 if (method->is_inflated)
8127 method = ((MonoMethodInflated *) method)->declaring;
8129 if (method->klass->image->dynamic) {
8130 MonoCustomAttrInfo *res, *ainfo;
8133 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8134 if (!aux || !aux->param_cattr)
8137 /* Need to copy since it will be freed later */
8138 ainfo = aux->param_cattr [param];
8139 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
8140 res = g_malloc0 (size);
8141 memcpy (res, ainfo, size);
8145 image = method->klass->image;
8146 method_index = mono_method_get_index (method);
8147 ca = &image->tables [MONO_TABLE_METHOD];
8149 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8150 if (method_index == ca->rows) {
8151 ca = &image->tables [MONO_TABLE_PARAM];
8152 param_last = ca->rows + 1;
8154 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8155 ca = &image->tables [MONO_TABLE_PARAM];
8158 for (i = param_list; i < param_last; ++i) {
8159 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8160 if (param_pos == param) {
8168 idx <<= MONO_CUSTOM_ATTR_BITS;
8169 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8170 return mono_custom_attrs_from_index (image, idx);
8174 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8178 for (i = 0; i < ainfo->num_attrs; ++i) {
8179 klass = ainfo->attrs [i].ctor->klass;
8180 if (mono_class_has_parent (klass, attr_klass))
8187 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8194 for (i = 0; i < ainfo->num_attrs; ++i) {
8195 klass = ainfo->attrs [i].ctor->klass;
8196 if (mono_class_has_parent (klass, attr_klass)) {
8201 if (attr_index == -1)
8204 attrs = mono_custom_attrs_construct (ainfo);
8206 return mono_array_get (attrs, MonoObject*, attr_index);
8212 * mono_reflection_get_custom_attrs_info:
8213 * @obj: a reflection object handle
8215 * Return the custom attribute info for attributes defined for the
8216 * reflection handle @obj. The objects.
8219 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8222 MonoCustomAttrInfo *cinfo = NULL;
8224 klass = obj->vtable->klass;
8225 if (klass == mono_defaults.monotype_class) {
8226 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8227 klass = mono_class_from_mono_type (rtype->type);
8228 cinfo = mono_custom_attrs_from_class (klass);
8229 } else if (strcmp ("Assembly", klass->name) == 0) {
8230 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8231 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8232 } else if (strcmp ("Module", klass->name) == 0) {
8233 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8234 cinfo = mono_custom_attrs_from_module (module->image);
8235 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8236 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8237 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8238 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8239 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
8240 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8241 } else if (strcmp ("MonoField", klass->name) == 0) {
8242 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8243 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8244 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8245 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8246 cinfo = mono_custom_attrs_from_method (rmethod->method);
8247 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8248 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8249 cinfo = mono_custom_attrs_from_method (rmethod->method);
8250 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8251 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8252 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8253 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8254 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8255 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8256 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8257 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8258 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8259 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8260 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8261 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8262 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8263 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8264 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8265 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8266 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8267 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8268 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8269 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8270 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8271 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8272 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8273 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8274 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8275 } else { /* handle other types here... */
8276 g_error ("get custom attrs not yet supported for %s", klass->name);
8283 * mono_reflection_get_custom_attrs_by_type:
8284 * @obj: a reflection object handle
8286 * Return an array with all the custom attributes defined of the
8287 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8288 * of that type are returned. The objects are fully build. Return NULL if a loading error
8292 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8295 MonoCustomAttrInfo *cinfo;
8297 cinfo = mono_reflection_get_custom_attrs_info (obj);
8300 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8302 result = mono_custom_attrs_construct (cinfo);
8304 mono_custom_attrs_free (cinfo);
8306 if (mono_loader_get_last_error ())
8308 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8315 * mono_reflection_get_custom_attrs:
8316 * @obj: a reflection object handle
8318 * Return an array with all the custom attributes defined of the
8319 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8323 mono_reflection_get_custom_attrs (MonoObject *obj)
8325 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8329 * mono_reflection_get_custom_attrs_data:
8330 * @obj: a reflection obj handle
8332 * Returns an array of System.Reflection.CustomAttributeData,
8333 * which include information about attributes reflected on
8334 * types loaded using the Reflection Only methods
8337 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8340 MonoCustomAttrInfo *cinfo;
8342 cinfo = mono_reflection_get_custom_attrs_info (obj);
8344 result = mono_custom_attrs_data_construct (cinfo);
8346 mono_custom_attrs_free (cinfo);
8348 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8353 static MonoReflectionType*
8354 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8356 MonoMethod *method_get_underlying_system_type;
8358 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8359 mono_class_get_method_from_name (mono_object_class (t),
8360 "get_UnderlyingSystemType",
8362 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8366 mono_reflection_type_get_handle (MonoReflectionType* t)
8371 t = mono_reflection_type_get_underlying_system_type (t);
8379 * LOCKING: Assumes the loader lock is held.
8381 static MonoMethodSignature*
8382 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
8383 MonoMethodSignature *sig;
8386 count = parameters? mono_array_length (parameters): 0;
8388 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8389 sig->param_count = count;
8390 sig->sentinelpos = -1; /* FIXME */
8391 for (i = 0; i < count; ++i) {
8392 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8393 sig->params [i] = mono_reflection_type_get_handle (pt);
8399 * LOCKING: Assumes the loader lock is held.
8401 static MonoMethodSignature*
8402 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
8403 MonoMethodSignature *sig;
8405 sig = parameters_to_signature (mp, ctor->parameters);
8406 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8407 sig->ret = &mono_defaults.void_class->byval_arg;
8412 * LOCKING: Assumes the loader lock is held.
8414 static MonoMethodSignature*
8415 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
8416 MonoMethodSignature *sig;
8418 sig = parameters_to_signature (mp, method->parameters);
8419 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8420 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8421 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8425 static MonoMethodSignature*
8426 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8427 MonoMethodSignature *sig;
8429 sig = parameters_to_signature (NULL, method->parameters);
8430 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8431 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8432 sig->generic_param_count = 0;
8437 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8439 MonoClass *klass = mono_object_class (prop);
8440 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8441 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8442 *name = mono_string_to_utf8 (pb->name);
8443 *type = pb->type->type;
8445 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8446 *name = g_strdup (p->property->name);
8447 if (p->property->get)
8448 *type = mono_method_signature (p->property->get)->ret;
8450 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8455 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8457 MonoClass *klass = mono_object_class (field);
8458 if (strcmp (klass->name, "FieldBuilder") == 0) {
8459 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8460 *name = mono_string_to_utf8 (fb->name);
8461 *type = fb->type->type;
8463 MonoReflectionField *f = (MonoReflectionField *)field;
8464 *name = g_strdup (mono_field_get_name (f->field));
8465 *type = f->field->type;
8470 * Encode a value in a custom attribute stream of bytes.
8471 * The value to encode is either supplied as an object in argument val
8472 * (valuetypes are boxed), or as a pointer to the data in the
8474 * @type represents the type of the value
8475 * @buffer is the start of the buffer
8476 * @p the current position in the buffer
8477 * @buflen contains the size of the buffer and is used to return the new buffer size
8478 * if this needs to be realloced.
8479 * @retbuffer and @retp return the start and the position of the buffer
8482 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8484 MonoTypeEnum simple_type;
8486 if ((p-buffer) + 10 >= *buflen) {
8489 newbuf = g_realloc (buffer, *buflen);
8490 p = newbuf + (p-buffer);
8494 argval = ((char*)arg + sizeof (MonoObject));
8495 simple_type = type->type;
8497 switch (simple_type) {
8498 case MONO_TYPE_BOOLEAN:
8503 case MONO_TYPE_CHAR:
8506 swap_with_size (p, argval, 2, 1);
8512 swap_with_size (p, argval, 4, 1);
8516 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8526 swap_with_size (p, argval, 8, 1);
8532 swap_with_size (p, argval, 8, 1);
8535 case MONO_TYPE_VALUETYPE:
8536 if (type->data.klass->enumtype) {
8537 simple_type = type->data.klass->enum_basetype->type;
8540 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8543 case MONO_TYPE_STRING: {
8550 str = mono_string_to_utf8 ((MonoString*)arg);
8551 slen = strlen (str);
8552 if ((p-buffer) + 10 + slen >= *buflen) {
8556 newbuf = g_realloc (buffer, *buflen);
8557 p = newbuf + (p-buffer);
8560 mono_metadata_encode_value (slen, p, &p);
8561 memcpy (p, str, slen);
8566 case MONO_TYPE_CLASS: {
8574 k = mono_object_class (arg);
8575 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8576 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8577 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8580 if (rt && (rtc = mono_object_class (rt)) &&
8581 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8582 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8583 arg = (MonoObject *) rt;
8586 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8589 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8590 slen = strlen (str);
8591 if ((p-buffer) + 10 + slen >= *buflen) {
8595 newbuf = g_realloc (buffer, *buflen);
8596 p = newbuf + (p-buffer);
8599 mono_metadata_encode_value (slen, p, &p);
8600 memcpy (p, str, slen);
8605 case MONO_TYPE_SZARRAY: {
8607 MonoClass *eclass, *arg_eclass;
8610 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8613 len = mono_array_length ((MonoArray*)arg);
8615 *p++ = (len >> 8) & 0xff;
8616 *p++ = (len >> 16) & 0xff;
8617 *p++ = (len >> 24) & 0xff;
8619 *retbuffer = buffer;
8620 eclass = type->data.klass;
8621 arg_eclass = mono_object_class (arg)->element_class;
8624 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8625 eclass = mono_defaults.object_class;
8627 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8628 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8629 int elsize = mono_class_array_element_size (arg_eclass);
8630 for (i = 0; i < len; ++i) {
8631 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8634 } else if (eclass->valuetype && arg_eclass->valuetype) {
8635 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8636 int elsize = mono_class_array_element_size (eclass);
8637 for (i = 0; i < len; ++i) {
8638 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8642 for (i = 0; i < len; ++i) {
8643 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8648 case MONO_TYPE_OBJECT: {
8654 * The parameter type is 'object' but the type of the actual
8655 * argument is not. So we have to add type information to the blob
8656 * too. This is completely undocumented in the spec.
8660 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8665 klass = mono_object_class (arg);
8667 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8670 } else if (klass->enumtype) {
8672 } else if (klass == mono_defaults.string_class) {
8673 simple_type = MONO_TYPE_STRING;
8676 } else if (klass->rank == 1) {
8678 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8679 /* See Partition II, Appendix B3 */
8682 *p++ = klass->element_class->byval_arg.type;
8683 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8685 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8686 *p++ = simple_type = klass->byval_arg.type;
8689 g_error ("unhandled type in custom attr");
8691 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8692 slen = strlen (str);
8693 if ((p-buffer) + 10 + slen >= *buflen) {
8697 newbuf = g_realloc (buffer, *buflen);
8698 p = newbuf + (p-buffer);
8701 mono_metadata_encode_value (slen, p, &p);
8702 memcpy (p, str, slen);
8705 simple_type = klass->enum_basetype->type;
8709 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8712 *retbuffer = buffer;
8716 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8718 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8719 char *str = type_get_qualified_name (type, NULL);
8720 int slen = strlen (str);
8724 * This seems to be optional...
8727 mono_metadata_encode_value (slen, p, &p);
8728 memcpy (p, str, slen);
8731 } else if (type->type == MONO_TYPE_OBJECT) {
8733 } else if (type->type == MONO_TYPE_CLASS) {
8734 /* it should be a type: encode_cattr_value () has the check */
8737 mono_metadata_encode_value (type->type, p, &p);
8738 if (type->type == MONO_TYPE_SZARRAY)
8739 /* See the examples in Partition VI, Annex B */
8740 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8747 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8750 /* Preallocate a large enough buffer */
8751 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8752 char *str = type_get_qualified_name (type, NULL);
8755 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8756 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8762 len += strlen (name);
8764 if ((p-buffer) + 20 + len >= *buflen) {
8768 newbuf = g_realloc (buffer, *buflen);
8769 p = newbuf + (p-buffer);
8773 encode_field_or_prop_type (type, p, &p);
8775 len = strlen (name);
8776 mono_metadata_encode_value (len, p, &p);
8777 memcpy (p, name, len);
8779 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8781 *retbuffer = buffer;
8784 #ifndef DISABLE_REFLECTION_EMIT
8787 * mono_reflection_get_custom_attrs_blob:
8788 * @ctor: custom attribute constructor
8789 * @ctorArgs: arguments o the constructor
8795 * Creates the blob of data that needs to be saved in the metadata and that represents
8796 * the custom attributed described by @ctor, @ctorArgs etc.
8797 * Returns: a Byte array representing the blob of data.
8800 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8803 MonoMethodSignature *sig;
8808 MONO_ARCH_SAVE_REGS;
8810 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8811 /* sig is freed later so allocate it in the heap */
8812 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8814 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8817 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8819 p = buffer = g_malloc (buflen);
8820 /* write the prolog */
8823 for (i = 0; i < sig->param_count; ++i) {
8824 arg = mono_array_get (ctorArgs, MonoObject*, i);
8825 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8829 i += mono_array_length (properties);
8831 i += mono_array_length (fields);
8833 *p++ = (i >> 8) & 0xff;
8836 for (i = 0; i < mono_array_length (properties); ++i) {
8840 prop = mono_array_get (properties, gpointer, i);
8841 get_prop_name_and_type (prop, &pname, &ptype);
8842 *p++ = 0x54; /* PROPERTY signature */
8843 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8850 for (i = 0; i < mono_array_length (fields); ++i) {
8854 field = mono_array_get (fields, gpointer, i);
8855 get_field_name_and_type (field, &fname, &ftype);
8856 *p++ = 0x53; /* FIELD signature */
8857 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8862 g_assert (p - buffer <= buflen);
8863 buflen = p - buffer;
8864 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8865 p = mono_array_addr (result, char, 0);
8866 memcpy (p, buffer, buflen);
8868 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8874 * mono_reflection_setup_internal_class:
8875 * @tb: a TypeBuilder object
8877 * Creates a MonoClass that represents the TypeBuilder.
8878 * This is a trick that lets us simplify a lot of reflection code
8879 * (and will allow us to support Build and Run assemblies easier).
8882 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8884 MonoClass *klass, *parent;
8886 MONO_ARCH_SAVE_REGS;
8888 mono_loader_lock ();
8891 /* check so we can compile corlib correctly */
8892 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8893 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8894 parent = tb->parent->type->data.klass;
8896 parent = my_mono_class_from_mono_type (tb->parent->type);
8902 /* the type has already being created: it means we just have to change the parent */
8903 if (tb->type.type) {
8904 klass = mono_class_from_mono_type (tb->type.type);
8905 klass->parent = NULL;
8906 /* fool mono_class_setup_parent */
8907 klass->supertypes = NULL;
8908 mono_class_setup_parent (klass, parent);
8909 mono_class_setup_mono_type (klass);
8910 mono_loader_unlock ();
8914 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
8916 klass->image = &tb->module->dynamic_image->image;
8918 klass->inited = 1; /* we lie to the runtime */
8919 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8920 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8921 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8922 klass->flags = tb->attrs;
8924 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8926 klass->element_class = klass;
8928 MOVING_GC_REGISTER (&klass->reflection_info);
8929 klass->reflection_info = tb;
8931 /* Put into cache so mono_class_get () will find it */
8932 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8934 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8935 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8937 if (parent != NULL) {
8938 mono_class_setup_parent (klass, parent);
8939 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8940 const char *old_n = klass->name;
8941 /* trick to get relative numbering right when compiling corlib */
8942 klass->name = "BuildingObject";
8943 mono_class_setup_parent (klass, mono_defaults.object_class);
8944 klass->name = old_n;
8947 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8948 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8949 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8950 klass->instance_size = sizeof (MonoObject);
8951 klass->size_inited = 1;
8952 mono_class_setup_vtable_general (klass, NULL, 0);
8955 mono_class_setup_mono_type (klass);
8957 mono_class_setup_supertypes (klass);
8960 * FIXME: handle interfaces.
8963 tb->type.type = &klass->byval_arg;
8965 if (tb->nesting_type) {
8966 g_assert (tb->nesting_type->type);
8967 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8970 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8972 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8974 mono_loader_unlock ();
8978 * mono_reflection_setup_generic_class:
8979 * @tb: a TypeBuilder object
8981 * Setup the generic class before adding the first generic parameter.
8984 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8988 MONO_ARCH_SAVE_REGS;
8990 klass = my_mono_class_from_mono_type (tb->type.type);
8991 if (tb->generic_container)
8994 tb->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
8995 tb->generic_container->owner.klass = klass;
8999 * mono_reflection_create_generic_class:
9000 * @tb: a TypeBuilder object
9002 * Creates the generic class after all generic parameters have been added.
9005 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9010 MONO_ARCH_SAVE_REGS;
9012 klass = my_mono_class_from_mono_type (tb->type.type);
9014 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9016 if (klass->generic_container || (count == 0))
9019 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9021 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9023 klass->generic_container->owner.klass = klass;
9024 klass->generic_container->type_argc = count;
9025 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParam) * count);
9027 for (i = 0; i < count; i++) {
9028 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9029 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
9030 /*Make sure we are a diferent type instance */
9031 klass->generic_container->type_params [i].owner = klass->generic_container;
9032 klass->generic_container->type_params [i].pklass = NULL;
9034 g_assert (klass->generic_container->type_params [i].owner);
9037 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9041 * mono_reflection_create_internal_class:
9042 * @tb: a TypeBuilder object
9044 * Actually create the MonoClass that is associated with the TypeBuilder.
9047 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9051 MONO_ARCH_SAVE_REGS;
9053 klass = my_mono_class_from_mono_type (tb->type.type);
9055 mono_loader_lock ();
9056 if (klass->enumtype && klass->enum_basetype == NULL) {
9057 MonoReflectionFieldBuilder *fb;
9060 g_assert (tb->fields != NULL);
9061 g_assert (mono_array_length (tb->fields) >= 1);
9063 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9065 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
9066 mono_loader_unlock ();
9070 klass->enum_basetype = fb->type->type;
9071 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
9072 if (!klass->element_class)
9073 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
9076 * get the element_class from the current corlib.
9078 ec = default_class_from_mono_type (klass->enum_basetype);
9079 klass->instance_size = ec->instance_size;
9080 klass->size_inited = 1;
9082 * this is almost safe to do with enums and it's needed to be able
9083 * to create objects of the enum type (for use in SetConstant).
9085 /* FIXME: Does this mean enums can't have method overrides ? */
9086 mono_class_setup_vtable_general (klass, NULL, 0);
9088 mono_loader_unlock ();
9091 #endif /* DISABLE_REFLECTION_EMIT */
9093 static MonoMarshalSpec*
9094 mono_marshal_spec_from_builder (MonoMemPool *mp, MonoAssembly *assembly,
9095 MonoReflectionMarshal *minfo)
9097 MonoMarshalSpec *res;
9099 res = mp_g_new0 (mp, MonoMarshalSpec, 1);
9100 res->native = minfo->type;
9102 switch (minfo->type) {
9103 case MONO_NATIVE_LPARRAY:
9104 res->data.array_data.elem_type = minfo->eltype;
9105 if (minfo->has_size) {
9106 res->data.array_data.param_num = minfo->param_num;
9107 res->data.array_data.num_elem = minfo->count;
9108 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9111 res->data.array_data.param_num = -1;
9112 res->data.array_data.num_elem = -1;
9113 res->data.array_data.elem_mult = -1;
9117 case MONO_NATIVE_BYVALTSTR:
9118 case MONO_NATIVE_BYVALARRAY:
9119 res->data.array_data.num_elem = minfo->count;
9122 case MONO_NATIVE_CUSTOM:
9123 if (minfo->marshaltyperef)
9124 res->data.custom_data.custom_name =
9125 type_get_fully_qualified_name (minfo->marshaltyperef->type);
9127 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9137 MonoReflectionMarshal*
9138 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9139 MonoMarshalSpec *spec)
9141 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9142 MonoReflectionMarshal *minfo;
9145 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9146 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9147 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9148 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9151 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9152 minfo->type = spec->native;
9154 switch (minfo->type) {
9155 case MONO_NATIVE_LPARRAY:
9156 minfo->eltype = spec->data.array_data.elem_type;
9157 minfo->count = spec->data.array_data.num_elem;
9158 minfo->param_num = spec->data.array_data.param_num;
9161 case MONO_NATIVE_BYVALTSTR:
9162 case MONO_NATIVE_BYVALARRAY:
9163 minfo->count = spec->data.array_data.num_elem;
9166 case MONO_NATIVE_CUSTOM:
9167 if (spec->data.custom_data.custom_name) {
9168 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9170 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9172 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9174 if (spec->data.custom_data.cookie)
9175 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9186 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9187 ReflectionMethodBuilder *rmb,
9188 MonoMethodSignature *sig)
9191 MonoMethodNormal *pm;
9192 MonoMarshalSpec **specs;
9193 MonoReflectionMethodAux *method_aux;
9199 * Methods created using a MethodBuilder should have their memory allocated
9200 * inside the image mempool, while dynamic methods should have their memory
9203 dynamic = rmb->refs != NULL;
9204 mp = dynamic ? NULL : klass->image->mempool;
9207 g_assert (!klass->generic_class);
9209 mono_loader_lock ();
9211 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9212 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9213 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
9215 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
9217 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
9219 pm = (MonoMethodNormal*)m;
9221 m->dynamic = dynamic;
9223 m->flags = rmb->attrs;
9224 m->iflags = rmb->iattrs;
9225 m->name = mp_string_to_utf8 (mp, rmb->name);
9228 m->skip_visibility = rmb->skip_visibility;
9230 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9232 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9233 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9236 m->signature->pinvoke = 1;
9237 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9238 m->signature->pinvoke = 1;
9240 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9242 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
9243 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
9245 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9247 if (klass->image->dynamic)
9248 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9250 mono_loader_unlock ();
9253 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9254 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9255 MonoMethodHeader *header;
9257 gint32 max_stack, i;
9258 gint32 num_locals = 0;
9259 gint32 num_clauses = 0;
9263 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9264 code_size = rmb->ilgen->code_len;
9265 max_stack = rmb->ilgen->max_stack;
9266 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9267 if (rmb->ilgen->ex_handlers)
9268 num_clauses = method_count_clauses (rmb->ilgen);
9271 code = mono_array_addr (rmb->code, guint8, 0);
9272 code_size = mono_array_length (rmb->code);
9273 /* we probably need to run a verifier on the code... */
9283 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
9284 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9285 header->code_size = code_size;
9286 header->code = mp_g_malloc (mp, code_size);
9287 memcpy ((char*)header->code, code, code_size);
9288 header->max_stack = max_stack;
9289 header->init_locals = rmb->init_locals;
9290 header->num_locals = num_locals;
9292 for (i = 0; i < num_locals; ++i) {
9293 MonoReflectionLocalBuilder *lb =
9294 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9296 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
9297 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9300 header->num_clauses = num_clauses;
9302 header->clauses = method_encode_clauses (mp, (MonoDynamicImage*)klass->image,
9303 rmb->ilgen, num_clauses);
9306 pm->header = header;
9309 if (rmb->generic_params) {
9310 int count = mono_array_length (rmb->generic_params);
9311 MonoGenericContainer *container;
9313 container = rmb->generic_container;
9315 m->is_generic = TRUE;
9316 mono_method_set_generic_container (m, container);
9318 container->type_argc = count;
9319 container->type_params = mp_g_new0 (mp, MonoGenericParam, count);
9320 container->owner.method = m;
9322 for (i = 0; i < count; i++) {
9323 MonoReflectionGenericParam *gp =
9324 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9326 container->type_params [i] = *gp->type.type->data.generic_param;
9329 if (klass->generic_container) {
9330 container->parent = klass->generic_container;
9331 container->context.class_inst = klass->generic_container->context.class_inst;
9333 container->context.method_inst = mono_get_shared_generic_inst (container);
9337 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9341 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9343 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
9344 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9345 for (i = 0; i < rmb->nrefs; ++i)
9346 data [i + 1] = rmb->refs [i];
9351 /* Parameter info */
9354 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9355 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
9356 for (i = 0; i <= m->signature->param_count; ++i) {
9357 MonoReflectionParamBuilder *pb;
9358 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9359 if ((i > 0) && (pb->attrs)) {
9360 /* Make a copy since it might point to a shared type structure */
9361 m->signature->params [i - 1] = mono_metadata_type_dup (mp, m->signature->params [i - 1]);
9362 m->signature->params [i - 1]->attrs = pb->attrs;
9365 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9366 MonoDynamicImage *assembly;
9367 guint32 idx, def_type, len;
9371 if (!method_aux->param_defaults) {
9372 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
9373 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
9375 assembly = (MonoDynamicImage*)klass->image;
9376 idx = encode_constant (assembly, pb->def_value, &def_type);
9377 /* Copy the data from the blob since it might get realloc-ed */
9378 p = assembly->blob.data + idx;
9379 len = mono_metadata_decode_blob_size (p, &p2);
9381 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
9382 method_aux->param_default_types [i] = def_type;
9383 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9387 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
9389 if (!method_aux->param_cattr)
9390 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
9391 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (mp, klass->image, pb->cattrs);
9397 /* Parameter marshalling */
9400 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9401 MonoReflectionParamBuilder *pb;
9402 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9403 if (pb->marshal_info) {
9405 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
9406 specs [pb->position] =
9407 mono_marshal_spec_from_builder (mp, klass->image->assembly, pb->marshal_info);
9411 if (specs != NULL) {
9413 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9414 method_aux->param_marshall = specs;
9417 if (klass->image->dynamic && method_aux)
9418 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9420 mono_loader_unlock ();
9426 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9428 ReflectionMethodBuilder rmb;
9429 MonoMethodSignature *sig;
9431 mono_loader_lock ();
9432 sig = ctor_builder_to_signature (klass->image->mempool, mb);
9433 mono_loader_unlock ();
9435 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9437 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9438 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9440 /* If we are in a generic class, we might be called multiple times from inflate_method */
9441 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9442 /* ilgen is no longer needed */
9450 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9452 ReflectionMethodBuilder rmb;
9453 MonoMethodSignature *sig;
9455 mono_loader_lock ();
9456 sig = method_builder_to_signature (klass->image->mempool, mb);
9457 mono_loader_unlock ();
9459 reflection_methodbuilder_from_method_builder (&rmb, mb);
9461 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9462 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9464 /* If we are in a generic class, we might be called multiple times from inflate_method */
9465 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9466 /* ilgen is no longer needed */
9472 static MonoClassField*
9473 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9475 MonoClassField *field;
9478 field = g_new0 (MonoClassField, 1);
9480 field->name = mono_string_to_utf8 (fb->name);
9481 if (fb->attrs || fb->modreq || fb->modopt) {
9482 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9483 field->type->attrs = fb->attrs;
9485 g_assert (klass->image->dynamic);
9486 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9487 g_free (field->type);
9488 field->type = custom;
9490 field->type = fb->type->type;
9492 if (fb->offset != -1)
9493 field->offset = fb->offset;
9494 field->parent = klass;
9495 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9497 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9503 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9506 MonoReflectionTypeBuilder *tb = NULL;
9507 gboolean is_dynamic = FALSE;
9511 mono_loader_lock ();
9513 domain = mono_object_domain (type);
9515 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9516 tb = (MonoReflectionTypeBuilder *) type;
9519 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9520 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9522 tb = rgi->generic_type;
9526 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9527 if (tb && tb->generic_container)
9528 mono_reflection_create_generic_class (tb);
9530 klass = mono_class_from_mono_type (type->type);
9531 if (!klass->generic_container) {
9532 mono_loader_unlock ();
9536 if (klass->wastypebuilder) {
9537 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9542 mono_loader_unlock ();
9544 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9546 return &geninst->byval_arg;
9550 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9552 MonoGenericClass *gclass;
9553 MonoGenericInst *inst;
9555 g_assert (klass->generic_container);
9557 inst = mono_metadata_get_generic_inst (type_argc, types);
9558 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9560 return mono_generic_class_get_class (gclass);
9563 MonoReflectionMethod*
9564 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9567 MonoMethod *method, *inflated;
9568 MonoMethodInflated *imethod;
9569 MonoReflectionMethodBuilder *mb = NULL;
9570 MonoGenericContext tmp_context;
9571 MonoGenericInst *ginst;
9572 MonoType **type_argv;
9575 MONO_ARCH_SAVE_REGS;
9577 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9578 #ifndef DISABLE_REFLECTION_EMIT
9579 MonoReflectionTypeBuilder *tb;
9582 mb = (MonoReflectionMethodBuilder *) rmethod;
9583 tb = (MonoReflectionTypeBuilder *) mb->type;
9584 klass = mono_class_from_mono_type (tb->type.type);
9586 method = methodbuilder_to_mono_method (klass, mb);
9588 g_assert_not_reached ();
9592 method = rmethod->method;
9595 klass = method->klass;
9597 if (method->is_inflated)
9598 method = ((MonoMethodInflated *) method)->declaring;
9600 count = mono_method_signature (method)->generic_param_count;
9601 if (count != mono_array_length (types))
9604 type_argv = g_new0 (MonoType *, count);
9605 for (i = 0; i < count; i++) {
9606 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9607 type_argv [i] = garg->type;
9609 ginst = mono_metadata_get_generic_inst (count, type_argv);
9612 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9613 tmp_context.method_inst = ginst;
9615 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9616 imethod = (MonoMethodInflated *) inflated;
9618 if (method->klass->image->dynamic) {
9619 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9621 * This table maps metadata structures representing inflated methods/fields
9622 * to the reflection objects representing their generic definitions.
9624 mono_loader_lock ();
9625 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9626 mono_loader_unlock ();
9629 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9632 #ifndef DISABLE_REFLECTION_EMIT
9635 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9637 MonoMethodInflated *imethod;
9638 MonoGenericContext *context;
9642 * With generic code sharing the klass might not be inflated.
9643 * This can happen because classes inflated with their own
9644 * type arguments are "normalized" to the uninflated class.
9646 if (!klass->generic_class)
9649 context = mono_class_get_context (klass);
9651 if (klass->method.count) {
9652 /* Find the already created inflated method */
9653 for (i = 0; i < klass->method.count; ++i) {
9654 g_assert (klass->methods [i]->is_inflated);
9655 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9658 g_assert (i < klass->method.count);
9659 imethod = (MonoMethodInflated*)klass->methods [i];
9661 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9664 if (method->is_generic && method->klass->image->dynamic) {
9665 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9667 mono_loader_lock ();
9668 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9669 mono_loader_unlock ();
9671 return (MonoMethod *) imethod;
9675 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9680 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9682 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9683 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9684 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9686 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9687 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9688 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9689 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9690 method = ((MonoReflectionMethod *) obj)->method;
9692 method = NULL; /* prevent compiler warning */
9693 g_assert_not_reached ();
9696 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9699 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9701 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9702 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9705 MonoGenericClass *gclass;
9706 MonoDynamicGenericClass *dgclass;
9707 MonoClass *klass, *gklass;
9710 MONO_ARCH_SAVE_REGS;
9712 klass = mono_class_from_mono_type (type->type.type);
9713 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9714 gclass = type->type.type->data.generic_class;
9716 g_assert (gclass->is_dynamic);
9717 dgclass = (MonoDynamicGenericClass *) gclass;
9719 if (dgclass->initialized)
9722 gklass = gclass->container_class;
9723 mono_class_init (gklass);
9725 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9726 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9727 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9728 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9729 dgclass->count_events = events ? mono_array_length (events) : 0;
9731 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9732 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9733 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9734 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9735 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9736 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
9737 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
9739 for (i = 0; i < dgclass->count_methods; i++) {
9740 MonoObject *obj = mono_array_get (methods, gpointer, i);
9742 dgclass->methods [i] = inflate_method (type, obj);
9745 for (i = 0; i < dgclass->count_ctors; i++) {
9746 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9748 dgclass->ctors [i] = inflate_method (type, obj);
9751 for (i = 0; i < dgclass->count_fields; i++) {
9752 MonoObject *obj = mono_array_get (fields, gpointer, i);
9753 MonoClassField *field, *inflated_field = NULL;
9755 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9756 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9757 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9758 field = ((MonoReflectionField *) obj)->field;
9760 field = NULL; /* prevent compiler warning */
9761 g_assert_not_reached ();
9764 dgclass->fields [i] = *field;
9765 dgclass->fields [i].parent = klass;
9766 dgclass->fields [i].type = mono_class_inflate_generic_type (
9767 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9768 dgclass->field_generic_types [i] = field->type;
9769 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
9770 dgclass->field_objects [i] = obj;
9772 if (inflated_field) {
9773 g_free (inflated_field);
9775 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9779 for (i = 0; i < dgclass->count_properties; i++) {
9780 MonoObject *obj = mono_array_get (properties, gpointer, i);
9781 MonoProperty *property = &dgclass->properties [i];
9783 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9784 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9786 property->parent = klass;
9787 property->attrs = pb->attrs;
9788 property->name = mono_string_to_utf8 (pb->name);
9790 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9792 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9793 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9794 *property = *((MonoReflectionProperty *) obj)->property;
9795 property->name = g_strdup (property->name);
9798 property->get = inflate_mono_method (klass, property->get, NULL);
9800 property->set = inflate_mono_method (klass, property->set, NULL);
9802 g_assert_not_reached ();
9805 for (i = 0; i < dgclass->count_events; i++) {
9806 MonoObject *obj = mono_array_get (events, gpointer, i);
9807 MonoEvent *event = &dgclass->events [i];
9809 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9810 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9812 event->parent = klass;
9813 event->attrs = eb->attrs;
9814 event->name = mono_string_to_utf8 (eb->name);
9816 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9817 if (eb->remove_method)
9818 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9819 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9820 *event = *((MonoReflectionEvent *) obj)->event;
9821 event->name = g_strdup (event->name);
9824 event->add = inflate_mono_method (klass, event->add, NULL);
9826 event->remove = inflate_mono_method (klass, event->remove, NULL);
9828 g_assert_not_reached ();
9831 dgclass->initialized = TRUE;
9835 ensure_generic_class_runtime_vtable (MonoClass *klass)
9837 MonoClass *gklass = klass->generic_class->container_class;
9840 if (klass->wastypebuilder)
9843 ensure_runtime_vtable (gklass);
9845 klass->method.count = gklass->method.count;
9846 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
9848 for (i = 0; i < klass->method.count; i++) {
9849 klass->methods [i] = mono_class_inflate_generic_method_full (
9850 gklass->methods [i], klass, mono_class_get_context (klass));
9853 klass->interface_count = gklass->interface_count;
9854 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9855 for (i = 0; i < klass->interface_count; ++i) {
9856 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
9857 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
9858 mono_metadata_free_type (iface_type);
9860 ensure_runtime_vtable (klass->interfaces [i]);
9862 /*We can only finish with this klass once it's parent has as well*/
9863 if (gklass->wastypebuilder)
9864 klass->wastypebuilder = TRUE;
9869 ensure_runtime_vtable (MonoClass *klass)
9871 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9874 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
9877 ensure_runtime_vtable (klass->parent);
9880 num = tb->ctors? mono_array_length (tb->ctors): 0;
9881 num += tb->num_methods;
9882 klass->method.count = num;
9883 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
9884 num = tb->ctors? mono_array_length (tb->ctors): 0;
9885 for (i = 0; i < num; ++i)
9886 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9887 num = tb->num_methods;
9889 for (i = 0; i < num; ++i)
9890 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9892 if (tb->interfaces) {
9893 klass->interface_count = mono_array_length (tb->interfaces);
9894 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9895 for (i = 0; i < klass->interface_count; ++i) {
9896 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9897 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9898 ensure_runtime_vtable (klass->interfaces [i]);
9901 } else if (klass->generic_class){
9902 ensure_generic_class_runtime_vtable (klass);
9905 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9906 for (i = 0; i < klass->method.count; ++i)
9907 klass->methods [i]->slot = i;
9909 mono_class_setup_interface_offsets (klass);
9910 mono_class_setup_interface_id (klass);
9914 * The generic vtable is needed even if image->run is not set since some
9915 * runtime code like ves_icall_Type_GetMethodsByName depends on
9916 * method->slot being defined.
9920 * tb->methods could not be freed since it is used for determining
9921 * overrides during dynamic vtable construction.
9926 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9928 MonoReflectionTypeBuilder *tb;
9934 g_assert (klass->image->dynamic);
9936 if (!klass->reflection_info)
9939 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9941 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9945 for (i = 0; i < tb->num_methods; ++i) {
9946 MonoReflectionMethodBuilder *mb =
9947 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9948 if (mb->override_method)
9954 *overrides = g_new0 (MonoMethod*, onum * 2);
9957 for (i = 0; i < tb->num_methods; ++i) {
9958 MonoReflectionMethodBuilder *mb =
9959 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9960 if (mb->override_method) {
9961 (*overrides) [onum * 2] =
9962 mb->override_method->method;
9963 (*overrides) [onum * 2 + 1] =
9966 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9967 g_assert (mb->override_method->method);
9968 g_assert (mb->mhandle);
9975 *num_overrides = onum;
9979 typebuilder_setup_fields (MonoClass *klass)
9981 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9982 MonoReflectionFieldBuilder *fb;
9983 MonoClassField *field;
9984 MonoMemPool *mp = klass->image->mempool;
9987 guint32 len, idx, real_size = 0;
9989 klass->field.count = tb->num_fields;
9990 klass->field.first = 0;
9992 if (tb->class_size) {
9993 g_assert ((tb->packing_size & 0xfffffff0) == 0);
9994 klass->packing_size = tb->packing_size;
9995 real_size = klass->instance_size + tb->class_size;
9998 if (!klass->field.count) {
9999 klass->instance_size = MAX (klass->instance_size, real_size);
10003 klass->fields = mp_g_new0 (mp, MonoClassField, klass->field.count);
10004 klass->field_def_values = mp_g_new0 (mp, MonoFieldDefaultValue, klass->field.count);
10006 for (i = 0; i < klass->field.count; ++i) {
10007 fb = mono_array_get (tb->fields, gpointer, i);
10008 field = &klass->fields [i];
10009 field->name = mp_string_to_utf8 (mp, fb->name);
10011 field->type = mono_metadata_type_dup (mp, fb->type->type);
10012 field->type->attrs = fb->attrs;
10014 field->type = fb->type->type;
10016 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10017 klass->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10018 if (fb->offset != -1)
10019 field->offset = fb->offset;
10020 field->parent = klass;
10021 fb->handle = field;
10022 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10024 if (fb->def_value) {
10025 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10026 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10027 idx = encode_constant (assembly, fb->def_value, &klass->field_def_values [i].def_type);
10028 /* Copy the data from the blob since it might get realloc-ed */
10029 p = assembly->blob.data + idx;
10030 len = mono_metadata_decode_blob_size (p, &p2);
10032 klass->field_def_values [i].data = mono_mempool_alloc (mp, len);
10033 memcpy ((gpointer)klass->field_def_values [i].data, p, len);
10037 klass->instance_size = MAX (klass->instance_size, real_size);
10038 mono_class_layout_fields (klass);
10042 typebuilder_setup_properties (MonoClass *klass)
10044 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10045 MonoReflectionPropertyBuilder *pb;
10046 MonoMemPool *mp = klass->image->mempool;
10049 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10050 klass->property.first = 0;
10052 klass->properties = mp_g_new0 (mp, MonoProperty, klass->property.count);
10053 for (i = 0; i < klass->property.count; ++i) {
10054 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10055 klass->properties [i].parent = klass;
10056 klass->properties [i].attrs = pb->attrs;
10057 klass->properties [i].name = mp_string_to_utf8 (mp, pb->name);
10058 if (pb->get_method)
10059 klass->properties [i].get = pb->get_method->mhandle;
10060 if (pb->set_method)
10061 klass->properties [i].set = pb->set_method->mhandle;
10063 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
10067 MonoReflectionEvent *
10068 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10070 MonoEvent *event = g_new0 (MonoEvent, 1);
10074 klass = my_mono_class_from_mono_type (tb->type.type);
10076 event->parent = klass;
10077 event->attrs = eb->attrs;
10078 event->name = mono_string_to_utf8 (eb->name);
10079 if (eb->add_method)
10080 event->add = eb->add_method->mhandle;
10081 if (eb->remove_method)
10082 event->remove = eb->remove_method->mhandle;
10083 if (eb->raise_method)
10084 event->raise = eb->raise_method->mhandle;
10086 if (eb->other_methods) {
10087 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10088 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10089 MonoReflectionMethodBuilder *mb =
10090 mono_array_get (eb->other_methods,
10091 MonoReflectionMethodBuilder*, j);
10092 event->other [j] = mb->mhandle;
10096 return mono_event_get_object (mono_object_domain (tb), klass, event);
10100 typebuilder_setup_events (MonoClass *klass)
10102 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10103 MonoReflectionEventBuilder *eb;
10104 MonoMemPool *mp = klass->image->mempool;
10107 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
10108 klass->event.first = 0;
10110 klass->events = mp_g_new0 (mp, MonoEvent, klass->event.count);
10111 for (i = 0; i < klass->event.count; ++i) {
10112 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10113 klass->events [i].parent = klass;
10114 klass->events [i].attrs = eb->attrs;
10115 klass->events [i].name = mp_string_to_utf8 (mp, eb->name);
10116 if (eb->add_method)
10117 klass->events [i].add = eb->add_method->mhandle;
10118 if (eb->remove_method)
10119 klass->events [i].remove = eb->remove_method->mhandle;
10120 if (eb->raise_method)
10121 klass->events [i].raise = eb->raise_method->mhandle;
10123 if (eb->other_methods) {
10124 klass->events [i].other = mp_g_new0 (mp, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10125 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10126 MonoReflectionMethodBuilder *mb =
10127 mono_array_get (eb->other_methods,
10128 MonoReflectionMethodBuilder*, j);
10129 klass->events [i].other [j] = mb->mhandle;
10132 mono_save_custom_attrs (klass->image, &klass->events [i], eb->cattrs);
10137 remove_instantiations_of (gpointer key,
10139 gpointer user_data)
10141 MonoType *type = (MonoType*)key;
10142 MonoClass *klass = (MonoClass*)user_data;
10144 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10150 MonoReflectionType*
10151 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10154 MonoDomain* domain;
10155 MonoReflectionType* res;
10158 MONO_ARCH_SAVE_REGS;
10160 domain = mono_object_domain (tb);
10161 klass = my_mono_class_from_mono_type (tb->type.type);
10163 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10166 * we need to lock the domain because the lock will be taken inside
10167 * So, we need to keep the locking order correct.
10169 mono_domain_lock (domain);
10170 mono_loader_lock ();
10171 if (klass->wastypebuilder) {
10172 mono_loader_unlock ();
10173 mono_domain_unlock (domain);
10174 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10177 * Fields to set in klass:
10178 * the various flags: delegate/unicode/contextbound etc.
10180 klass->flags = tb->attrs;
10181 klass->has_cctor = 1;
10182 klass->has_finalize = 1;
10185 if (!((MonoDynamicImage*)klass->image)->run) {
10186 if (klass->generic_container) {
10187 /* FIXME: The code below can't handle generic classes */
10188 klass->wastypebuilder = TRUE;
10189 mono_loader_unlock ();
10190 mono_domain_unlock (domain);
10191 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10196 /* enums are done right away */
10197 if (!klass->enumtype)
10198 ensure_runtime_vtable (klass);
10200 if (tb->subtypes) {
10201 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10202 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10203 klass->nested_classes = g_list_prepend_mempool (klass->image->mempool, klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
10207 klass->nested_classes_inited = TRUE;
10209 /* fields and object layout */
10210 if (klass->parent) {
10211 if (!klass->parent->size_inited)
10212 mono_class_init (klass->parent);
10213 klass->instance_size = klass->parent->instance_size;
10214 klass->sizes.class_size = 0;
10215 klass->min_align = klass->parent->min_align;
10216 /* if the type has no fields we won't call the field_setup
10217 * routine which sets up klass->has_references.
10219 klass->has_references |= klass->parent->has_references;
10221 klass->instance_size = sizeof (MonoObject);
10222 klass->min_align = 1;
10225 /* FIXME: handle packing_size and instance_size */
10226 typebuilder_setup_fields (klass);
10228 typebuilder_setup_properties (klass);
10230 typebuilder_setup_events (klass);
10232 klass->wastypebuilder = TRUE;
10235 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10236 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10237 * we want to return normal System.MonoType objects, so clear these out from the cache.
10239 if (domain->type_hash && klass->generic_container)
10240 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10242 mono_loader_unlock ();
10243 mono_domain_unlock (domain);
10245 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10246 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10247 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10250 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10251 g_assert (res != (MonoReflectionType*)tb);
10257 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10259 MonoGenericParam *param;
10262 MONO_ARCH_SAVE_REGS;
10264 param = g_new0 (MonoGenericParam, 1);
10266 if (gparam->mbuilder) {
10267 if (!gparam->mbuilder->generic_container) {
10268 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10269 MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
10270 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10271 gparam->mbuilder->generic_container->is_method = TRUE;
10273 param->owner = gparam->mbuilder->generic_container;
10274 } else if (gparam->tbuilder) {
10275 g_assert (gparam->tbuilder->generic_container);
10276 param->owner = gparam->tbuilder->generic_container;
10279 param->name = mono_string_to_utf8 (gparam->name);
10280 param->num = gparam->index;
10282 image = &gparam->tbuilder->module->dynamic_image->image;
10283 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10285 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
10286 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10288 gparam->type.type = g_new0 (MonoType, 1);
10289 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
10290 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
10291 gparam->type.type->data.generic_param = param;
10295 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10297 MonoDynamicImage *assembly = sig->module->dynamic_image;
10298 guint32 na = mono_array_length (sig->arguments);
10303 sigbuffer_init (&buf, 32);
10305 sigbuffer_add_value (&buf, 0x07);
10306 sigbuffer_add_value (&buf, na);
10307 for (i = 0; i < na; ++i) {
10308 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10309 encode_reflection_type (assembly, type, &buf);
10312 buflen = buf.p - buf.buf;
10313 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10314 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10315 sigbuffer_free (&buf);
10321 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10323 MonoDynamicImage *assembly = sig->module->dynamic_image;
10324 guint32 na = mono_array_length (sig->arguments);
10329 sigbuffer_init (&buf, 32);
10331 sigbuffer_add_value (&buf, 0x06);
10332 for (i = 0; i < na; ++i) {
10333 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10334 encode_reflection_type (assembly, type, &buf);
10337 buflen = buf.p - buf.buf;
10338 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10339 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10340 sigbuffer_free (&buf);
10346 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10348 ReflectionMethodBuilder rmb;
10349 MonoMethodSignature *sig;
10354 sig = dynamic_method_to_signature (mb);
10356 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10359 * Resolve references.
10362 * Every second entry in the refs array is reserved for storing handle_class,
10363 * which is needed by the ldtoken implementation in the JIT.
10365 rmb.nrefs = mb->nrefs;
10366 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10367 for (i = 0; i < mb->nrefs; i += 2) {
10368 MonoClass *handle_class;
10370 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10372 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10373 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10375 * The referenced DynamicMethod should already be created by the managed
10376 * code, except in the case of circular references. In that case, we store
10377 * method in the refs array, and fix it up later when the referenced
10378 * DynamicMethod is created.
10380 if (method->mhandle) {
10381 ref = method->mhandle;
10383 /* FIXME: GC object stored in unmanaged memory */
10386 /* FIXME: GC object stored in unmanaged memory */
10387 method->referenced_by = g_slist_append (method->referenced_by, mb);
10389 handle_class = mono_defaults.methodhandle_class;
10391 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10394 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10399 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10400 rmb.refs [i + 1] = handle_class;
10403 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10405 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10407 /* Fix up refs entries pointing at us */
10408 for (l = mb->referenced_by; l; l = l->next) {
10409 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10410 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10413 g_assert (method->mhandle);
10415 data = (gpointer*)wrapper->method_data;
10416 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10417 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10418 data [i + 1] = mb->mhandle;
10421 g_slist_free (mb->referenced_by);
10425 /* ilgen is no longer needed */
10429 #endif /* DISABLE_REFLECTION_EMIT */
10432 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10437 mono_runtime_free_method (
10438 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10443 * mono_reflection_is_valid_dynamic_token:
10445 * Returns TRUE if token is valid.
10449 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10451 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10454 #ifndef DISABLE_REFLECTION_EMIT
10457 * mono_reflection_lookup_dynamic_token:
10459 * Finish the Builder object pointed to by TOKEN and return the corresponding
10460 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10461 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10465 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10467 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10471 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10474 g_assert_not_reached ();
10480 handle_class = &klass;
10481 return resolve_object (image, obj, handle_class, context);
10485 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10487 gpointer result = NULL;
10489 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10490 result = mono_string_intern ((MonoString*)obj);
10491 *handle_class = NULL;
10493 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10494 MonoReflectionType *tb = (MonoReflectionType*)obj;
10496 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10497 result = mono_class_from_mono_type (inflated);
10498 mono_metadata_free_type (inflated);
10500 result = mono_class_from_mono_type (tb->type);
10502 *handle_class = mono_defaults.typehandle_class;
10504 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10505 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10506 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10507 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10508 result = ((MonoReflectionMethod*)obj)->method;
10510 result = mono_class_inflate_generic_method (result, context);
10511 *handle_class = mono_defaults.methodhandle_class;
10513 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10514 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10515 result = mb->mhandle;
10517 /* Type is not yet created */
10518 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10520 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10523 * Hopefully this has been filled in by calling CreateType() on the
10527 * TODO: This won't work if the application finishes another
10528 * TypeBuilder instance instead of this one.
10530 result = mb->mhandle;
10533 result = mono_class_inflate_generic_method (result, context);
10534 *handle_class = mono_defaults.methodhandle_class;
10535 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10536 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10538 result = cb->mhandle;
10540 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10542 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10543 result = cb->mhandle;
10546 result = mono_class_inflate_generic_method (result, context);
10547 *handle_class = mono_defaults.methodhandle_class;
10548 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10549 result = ((MonoReflectionField*)obj)->field;
10550 *handle_class = mono_defaults.fieldhandle_class;
10552 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10553 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10554 result = fb->handle;
10557 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10559 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10560 result = fb->handle;
10563 if (fb->handle && fb->handle->parent->generic_container) {
10564 MonoClass *klass = fb->handle->parent;
10565 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10566 MonoClass *inflated = mono_class_from_mono_type (type);
10568 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
10570 mono_metadata_free_type (type);
10572 *handle_class = mono_defaults.fieldhandle_class;
10573 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10574 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10577 klass = tb->type.type->data.klass;
10578 if (klass->wastypebuilder) {
10579 /* Already created */
10583 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10584 result = tb->type.type->data.klass;
10587 *handle_class = mono_defaults.typehandle_class;
10588 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10589 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10590 MonoMethodSignature *sig;
10593 if (helper->arguments)
10594 nargs = mono_array_length (helper->arguments);
10598 sig = mono_metadata_signature_alloc (image, nargs);
10599 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10600 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10602 if (helper->call_conv == 0) /* unmanaged */
10603 sig->call_convention = helper->unmanaged_call_conv - 1;
10605 if (helper->call_conv & 0x02)
10606 sig->call_convention = MONO_CALL_VARARG;
10608 sig->call_convention = MONO_CALL_DEFAULT;
10610 sig->param_count = nargs;
10611 /* TODO: Copy type ? */
10612 sig->ret = helper->return_type->type;
10613 for (i = 0; i < nargs; ++i) {
10614 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10615 sig->params [i] = rt->type;
10619 *handle_class = NULL;
10620 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10621 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10622 /* Already created by the managed code */
10623 g_assert (method->mhandle);
10624 result = method->mhandle;
10625 *handle_class = mono_defaults.methodhandle_class;
10626 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10627 MonoReflectionType *tb = (MonoReflectionType*)obj;
10628 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10629 result = mono_class_from_mono_type (type);
10630 *handle_class = mono_defaults.typehandle_class;
10632 mono_metadata_free_type (type);
10633 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10634 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10635 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10636 result = mono_class_from_mono_type (type);
10637 *handle_class = mono_defaults.typehandle_class;
10639 mono_metadata_free_type (type);
10640 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10641 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10642 MonoClass *inflated;
10645 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10646 inflated = mono_class_from_mono_type (type);
10648 g_assert (f->fb->handle);
10649 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
10651 mono_metadata_free_type (type);
10652 *handle_class = mono_defaults.fieldhandle_class;
10653 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10654 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10655 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10656 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10657 g_assert (c->cb->mhandle);
10658 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10659 *handle_class = mono_defaults.methodhandle_class;
10660 mono_metadata_free_type (type);
10661 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10662 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10663 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10664 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10665 g_assert (m->mb->mhandle);
10666 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10667 *handle_class = mono_defaults.methodhandle_class;
10668 mono_metadata_free_type (type);
10670 g_print (obj->vtable->klass->name);
10671 g_assert_not_reached ();
10676 #else /* DISABLE_REFLECTION_EMIT */
10679 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10681 g_assert_not_reached ();
10686 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10688 g_assert_not_reached ();
10692 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10694 g_assert_not_reached ();
10698 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10700 g_assert_not_reached ();
10704 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10706 g_assert_not_reached ();
10710 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
10712 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10716 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
10718 g_assert_not_reached ();
10721 MonoReflectionModule *
10722 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
10724 g_assert_not_reached ();
10729 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
10731 g_assert_not_reached ();
10736 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
10738 g_assert_not_reached ();
10743 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
10744 gboolean create_methodspec, gboolean register_token)
10746 g_assert_not_reached ();
10751 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
10756 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10757 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10760 g_assert_not_reached ();
10764 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10767 *num_overrides = 0;
10770 MonoReflectionEvent *
10771 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10773 g_assert_not_reached ();
10777 MonoReflectionType*
10778 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10780 g_assert_not_reached ();
10785 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10787 g_assert_not_reached ();
10791 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10793 g_assert_not_reached ();
10798 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10800 g_assert_not_reached ();
10805 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10810 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10815 #endif /* DISABLE_REFLECTION_EMIT */
10817 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10818 const static guint32 declsec_flags_map[] = {
10819 0x00000000, /* empty */
10820 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10821 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10822 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10823 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10824 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10825 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10826 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10827 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10828 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10829 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10830 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10831 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10832 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10833 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10834 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10835 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10836 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10837 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10841 * Returns flags that includes all available security action associated to the handle.
10842 * @token: metadata token (either for a class or a method)
10843 * @image: image where resides the metadata.
10846 mono_declsec_get_flags (MonoImage *image, guint32 token)
10848 int index = mono_metadata_declsec_from_index (image, token);
10849 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10850 guint32 result = 0;
10854 /* HasSecurity can be present for other, not specially encoded, attributes,
10855 e.g. SuppressUnmanagedCodeSecurityAttribute */
10859 for (i = index; i < t->rows; i++) {
10860 guint32 cols [MONO_DECL_SECURITY_SIZE];
10862 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10863 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10866 action = cols [MONO_DECL_SECURITY_ACTION];
10867 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10868 result |= declsec_flags_map [action];
10870 g_assert_not_reached ();
10877 * Get the security actions (in the form of flags) associated with the specified method.
10879 * @method: The method for which we want the declarative security flags.
10880 * Return the declarative security flags for the method (only).
10882 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10883 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10886 mono_declsec_flags_from_method (MonoMethod *method)
10888 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10889 /* FIXME: No cache (for the moment) */
10890 guint32 idx = mono_method_get_index (method);
10891 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10892 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10893 return mono_declsec_get_flags (method->klass->image, idx);
10899 * Get the security actions (in the form of flags) associated with the specified class.
10901 * @klass: The class for which we want the declarative security flags.
10902 * Return the declarative security flags for the class.
10904 * Note: We cache the flags inside the MonoClass structure as this will get
10905 * called very often (at least for each method).
10908 mono_declsec_flags_from_class (MonoClass *klass)
10910 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10911 if (!klass->declsec_flags) {
10912 guint32 idx = mono_metadata_token_index (klass->type_token);
10913 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10914 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10915 /* we cache the flags on classes */
10916 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10918 return klass->declsec_flags;
10924 * Get the security actions (in the form of flags) associated with the specified assembly.
10926 * @assembly: The assembly for which we want the declarative security flags.
10927 * Return the declarative security flags for the assembly.
10930 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10932 guint32 idx = 1; /* there is only one assembly */
10933 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10934 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10935 return mono_declsec_get_flags (assembly->image, idx);
10940 * Fill actions for the specific index (which may either be an encoded class token or
10941 * an encoded method token) from the metadata image.
10942 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10945 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10946 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10948 MonoBoolean result = FALSE;
10950 guint32 cols [MONO_DECL_SECURITY_SIZE];
10951 int index = mono_metadata_declsec_from_index (image, token);
10954 t = &image->tables [MONO_TABLE_DECLSECURITY];
10955 for (i = index; i < t->rows; i++) {
10956 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10958 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10961 /* if present only replace (class) permissions with method permissions */
10962 /* if empty accept either class or method permissions */
10963 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10964 if (!actions->demand.blob) {
10965 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10966 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10967 actions->demand.blob = (char*) (blob + 2);
10968 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10971 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10972 if (!actions->noncasdemand.blob) {
10973 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10974 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10975 actions->noncasdemand.blob = (char*) (blob + 2);
10976 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10979 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10980 if (!actions->demandchoice.blob) {
10981 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10982 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10983 actions->demandchoice.blob = (char*) (blob + 2);
10984 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10994 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
10995 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10997 guint32 idx = mono_metadata_token_index (klass->type_token);
10998 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10999 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11000 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11004 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11005 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11007 guint32 idx = mono_method_get_index (method);
11008 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11009 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11010 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11014 * Collect all actions (that requires to generate code in mini) assigned for
11015 * the specified method.
11016 * Note: Don't use the content of actions if the function return FALSE.
11019 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11021 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11022 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11023 MonoBoolean result = FALSE;
11026 /* quick exit if no declarative security is present in the metadata */
11027 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11030 /* we want the original as the wrapper is "free" of the security informations */
11031 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11032 method = mono_marshal_method_from_wrapper (method);
11037 /* First we look for method-level attributes */
11038 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11039 mono_class_init (method->klass);
11040 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11042 result = mono_declsec_get_method_demands_params (method, demands,
11043 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11046 /* Here we use (or create) the class declarative cache to look for demands */
11047 flags = mono_declsec_flags_from_class (method->klass);
11048 if (flags & mask) {
11050 mono_class_init (method->klass);
11051 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11053 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11054 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11057 /* The boolean return value is used as a shortcut in case nothing needs to
11058 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11064 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11066 * Note: Don't use the content of actions if the function return FALSE.
11069 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11071 MonoBoolean result = FALSE;
11074 /* quick exit if no declarative security is present in the metadata */
11075 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11078 /* we want the original as the wrapper is "free" of the security informations */
11079 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11080 method = mono_marshal_method_from_wrapper (method);
11085 /* results are independant - zeroize both */
11086 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11087 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11089 /* First we look for method-level attributes */
11090 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11091 mono_class_init (method->klass);
11093 result = mono_declsec_get_method_demands_params (method, cmethod,
11094 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11097 /* Here we use (or create) the class declarative cache to look for demands */
11098 flags = mono_declsec_flags_from_class (method->klass);
11099 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11100 mono_class_init (method->klass);
11102 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11103 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11110 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11112 * @klass The inherited class - this is the class that provides the security check (attributes)
11114 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11116 * Note: Don't use the content of actions if the function return FALSE.
11119 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11121 MonoBoolean result = FALSE;
11124 /* quick exit if no declarative security is present in the metadata */
11125 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11128 /* Here we use (or create) the class declarative cache to look for demands */
11129 flags = mono_declsec_flags_from_class (klass);
11130 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11131 mono_class_init (klass);
11132 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11134 result |= mono_declsec_get_class_demands_params (klass, demands,
11135 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11142 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11144 * Note: Don't use the content of actions if the function return FALSE.
11147 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11149 /* quick exit if no declarative security is present in the metadata */
11150 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11153 /* we want the original as the wrapper is "free" of the security informations */
11154 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11155 method = mono_marshal_method_from_wrapper (method);
11160 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11161 mono_class_init (method->klass);
11162 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11164 return mono_declsec_get_method_demands_params (method, demands,
11165 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11172 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11174 guint32 cols [MONO_DECL_SECURITY_SIZE];
11178 int index = mono_metadata_declsec_from_index (image, token);
11182 t = &image->tables [MONO_TABLE_DECLSECURITY];
11183 for (i = index; i < t->rows; i++) {
11184 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11186 /* shortcut - index are ordered */
11187 if (token != cols [MONO_DECL_SECURITY_PARENT])
11190 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11191 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11192 entry->blob = (char*) (metadata + 2);
11193 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11202 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11204 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11205 guint32 idx = mono_method_get_index (method);
11206 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11207 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11208 return get_declsec_action (method->klass->image, idx, action, entry);
11214 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11217 guint32 flags = mono_declsec_flags_from_class (klass);
11218 if (declsec_flags_map [action] & flags) {
11219 guint32 idx = mono_metadata_token_index (klass->type_token);
11220 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11221 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11222 return get_declsec_action (klass->image, idx, action, entry);
11228 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11230 guint32 idx = 1; /* there is only one assembly */
11231 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11232 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11234 return get_declsec_action (assembly->image, idx, action, entry);
11238 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11240 MonoObject *res, *exc;
11242 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11243 static MonoMethod *method = NULL;
11245 if (!System_Reflection_Emit_TypeBuilder) {
11246 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11247 g_assert (System_Reflection_Emit_TypeBuilder);
11249 if (method == NULL) {
11250 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11255 * The result of mono_type_get_object () might be a System.MonoType but we
11256 * need a TypeBuilder so use klass->reflection_info.
11258 g_assert (klass->reflection_info);
11259 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11261 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11263 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11267 return *(MonoBoolean*)mono_object_unbox (res);