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 "rawbuffer.h"
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
46 #define TEXT_OFFSET 512
47 #define CLI_H_SIZE 136
48 #define FILE_ALIGN 512
49 #define VIRT_ALIGN 8192
50 #define START_TEXT_RVA 0x00002000
53 MonoReflectionILGen *ilgen;
54 MonoReflectionType *rtype;
55 MonoArray *parameters;
56 MonoArray *generic_params;
57 MonoGenericContainer *generic_container;
63 guint32 *table_idx; /* note: it's a pointer */
67 MonoBoolean init_locals;
68 MonoBoolean skip_visibility;
69 MonoArray *return_modreq;
70 MonoArray *return_modopt;
71 MonoArray *param_modreq;
72 MonoArray *param_modopt;
73 MonoArray *permissions;
78 int charset, extra_flags, native_cc;
79 MonoString *dll, *dllentry;
80 } ReflectionMethodBuilder;
84 MonoReflectionGenericParam *gparam;
85 } GenericParamTableEntry;
87 const unsigned char table_sizes [MONO_TABLE_NUM] = {
97 MONO_INTERFACEIMPL_SIZE,
98 MONO_MEMBERREF_SIZE, /* 0x0A */
100 MONO_CUSTOM_ATTR_SIZE,
101 MONO_FIELD_MARSHAL_SIZE,
102 MONO_DECL_SECURITY_SIZE,
103 MONO_CLASS_LAYOUT_SIZE,
104 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
105 MONO_STAND_ALONE_SIGNATURE_SIZE,
109 MONO_PROPERTY_MAP_SIZE,
112 MONO_METHOD_SEMA_SIZE,
113 MONO_METHODIMPL_SIZE,
114 MONO_MODULEREF_SIZE, /* 0x1A */
120 MONO_ASSEMBLY_SIZE, /* 0x20 */
121 MONO_ASSEMBLY_PROCESSOR_SIZE,
122 MONO_ASSEMBLYOS_SIZE,
123 MONO_ASSEMBLYREF_SIZE,
124 MONO_ASSEMBLYREFPROC_SIZE,
125 MONO_ASSEMBLYREFOS_SIZE,
129 MONO_NESTED_CLASS_SIZE,
131 MONO_GENERICPARAM_SIZE, /* 0x2A */
132 MONO_METHODSPEC_SIZE,
133 MONO_GENPARCONSTRAINT_SIZE
137 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
138 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
139 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
140 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
141 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
142 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
143 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
144 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
145 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
146 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
147 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
148 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
149 static void ensure_runtime_vtable (MonoClass *klass);
150 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
151 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
152 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
153 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
154 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
155 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
156 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
158 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
159 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
160 static CRITICAL_SECTION reflection_mutex;
163 mono_reflection_init (void)
165 InitializeCriticalSection (&reflection_mutex);
169 sigbuffer_init (SigBuffer *buf, int size)
171 buf->buf = g_malloc (size);
173 buf->end = buf->buf + size;
177 sigbuffer_make_room (SigBuffer *buf, int size)
179 if (buf->end - buf->p < size) {
180 int new_size = buf->end - buf->buf + size + 32;
181 char *p = g_realloc (buf->buf, new_size);
182 size = buf->p - buf->buf;
185 buf->end = buf->buf + new_size;
190 sigbuffer_add_value (SigBuffer *buf, guint32 val)
192 sigbuffer_make_room (buf, 6);
193 mono_metadata_encode_value (val, buf->p, &buf->p);
197 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
199 sigbuffer_make_room (buf, 1);
205 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
207 sigbuffer_make_room (buf, size);
208 memcpy (buf->p, p, size);
213 sigbuffer_free (SigBuffer *buf)
221 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
225 mp_g_malloc (MonoMemPool *mp, guint size)
228 return mono_mempool_alloc (mp, size);
230 return g_malloc (size);
236 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
240 mp_g_malloc0 (MonoMemPool *mp, guint size)
243 return mono_mempool_alloc0 (mp, size);
245 return g_malloc0 (size);
251 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
252 * memory from the C heap.
255 mp_string_to_utf8 (MonoMemPool *mp, MonoString *s)
258 return mono_string_to_utf8_mp (mp, s);
260 return mono_string_to_utf8 (s);
263 #define mp_g_new(mp,struct_type, n_structs) \
264 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
266 #define mp_g_new0(mp,struct_type, n_structs) \
267 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
270 alloc_table (MonoDynamicTable *table, guint nrows)
273 g_assert (table->columns);
274 if (nrows + 1 >= table->alloc_rows) {
275 while (nrows + 1 >= table->alloc_rows) {
276 if (table->alloc_rows == 0)
277 table->alloc_rows = 16;
279 table->alloc_rows *= 2;
282 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
287 make_room_in_stream (MonoDynamicStream *stream, int size)
289 if (size <= stream->alloc_size)
292 while (stream->alloc_size <= size) {
293 if (stream->alloc_size < 4096)
294 stream->alloc_size = 4096;
296 stream->alloc_size *= 2;
299 stream->data = g_realloc (stream->data, stream->alloc_size);
303 string_heap_insert (MonoDynamicStream *sh, const char *str)
307 gpointer oldkey, oldval;
309 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
310 return GPOINTER_TO_UINT (oldval);
312 len = strlen (str) + 1;
315 make_room_in_stream (sh, idx + len);
318 * We strdup the string even if we already copy them in sh->data
319 * so that the string pointers in the hash remain valid even if
320 * we need to realloc sh->data. We may want to avoid that later.
322 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
323 memcpy (sh->data + idx, str, len);
329 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
331 char *name = mono_string_to_utf8 (str);
333 idx = string_heap_insert (sh, name);
339 string_heap_init (MonoDynamicStream *sh)
342 sh->alloc_size = 4096;
343 sh->data = g_malloc (4096);
344 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
345 string_heap_insert (sh, "");
349 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
353 make_room_in_stream (stream, stream->index + len);
354 memcpy (stream->data + stream->index, data, len);
356 stream->index += len;
358 * align index? Not without adding an additional param that controls it since
359 * we may store a blob value in pieces.
365 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
369 make_room_in_stream (stream, stream->index + len);
370 memset (stream->data + stream->index, 0, len);
372 stream->index += len;
377 stream_data_align (MonoDynamicStream *stream)
380 guint32 count = stream->index % 4;
382 /* we assume the stream data will be aligned */
384 mono_image_add_stream_data (stream, buf, 4 - count);
388 mono_blob_entry_hash (const char* str)
392 len = mono_metadata_decode_blob_size (str, &str);
396 for (str += 1; str < end; str++)
397 h = (h << 5) - h + *str;
405 mono_blob_entry_equal (const char *str1, const char *str2) {
409 len = mono_metadata_decode_blob_size (str1, &end1);
410 len2 = mono_metadata_decode_blob_size (str2, &end2);
413 return memcmp (end1, end2, len) == 0;
417 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
421 gpointer oldkey, oldval;
423 copy = g_malloc (s1+s2);
424 memcpy (copy, b1, s1);
425 memcpy (copy + s1, b2, s2);
426 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
428 idx = GPOINTER_TO_UINT (oldval);
430 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
431 mono_image_add_stream_data (&assembly->blob, b2, s2);
432 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
438 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
442 guint32 size = buf->p - buf->buf;
444 g_assert (size <= (buf->end - buf->buf));
445 mono_metadata_encode_value (size, b, &b);
446 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
450 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
451 * dest may be misaligned.
454 swap_with_size (char *dest, const char* val, int len, int nelem) {
455 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
458 for (elem = 0; elem < nelem; ++elem) {
484 g_assert_not_reached ();
490 memcpy (dest, val, len * nelem);
495 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
499 guint32 idx = 0, len;
501 len = str->length * 2;
502 mono_metadata_encode_value (len, b, &b);
503 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
505 char *swapped = g_malloc (2 * mono_string_length (str));
506 const char *p = (const char*)mono_string_chars (str);
508 swap_with_size (swapped, p, 2, mono_string_length (str));
509 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
513 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
518 /* modified version needed to handle building corlib */
520 my_mono_class_from_mono_type (MonoType *type) {
521 switch (type->type) {
522 case MONO_TYPE_ARRAY:
524 case MONO_TYPE_SZARRAY:
525 case MONO_TYPE_GENERICINST:
526 return mono_class_from_mono_type (type);
529 g_assert (type->data.generic_param->pklass);
530 return type->data.generic_param->pklass;
532 /* should be always valid when we reach this case... */
533 return type->data.klass;
538 default_class_from_mono_type (MonoType *type)
540 switch (type->type) {
541 case MONO_TYPE_OBJECT:
542 return mono_defaults.object_class;
544 return mono_defaults.void_class;
545 case MONO_TYPE_BOOLEAN:
546 return mono_defaults.boolean_class;
548 return mono_defaults.char_class;
550 return mono_defaults.sbyte_class;
552 return mono_defaults.byte_class;
554 return mono_defaults.int16_class;
556 return mono_defaults.uint16_class;
558 return mono_defaults.int32_class;
560 return mono_defaults.uint32_class;
562 return mono_defaults.int_class;
564 return mono_defaults.uint_class;
566 return mono_defaults.int64_class;
568 return mono_defaults.uint64_class;
570 return mono_defaults.single_class;
572 return mono_defaults.double_class;
573 case MONO_TYPE_STRING:
574 return mono_defaults.string_class;
576 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
577 g_assert_not_reached ();
584 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
587 MonoGenericInst *class_inst;
592 class_inst = gclass->context.class_inst;
594 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
595 klass = gclass->container_class;
596 sigbuffer_add_value (buf, klass->byval_arg.type);
597 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
599 sigbuffer_add_value (buf, class_inst->type_argc);
600 for (i = 0; i < class_inst->type_argc; ++i)
601 encode_type (assembly, class_inst->type_argv [i], buf);
606 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
609 g_assert_not_reached ();
614 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
618 case MONO_TYPE_BOOLEAN:
632 case MONO_TYPE_STRING:
633 case MONO_TYPE_OBJECT:
634 case MONO_TYPE_TYPEDBYREF:
635 sigbuffer_add_value (buf, type->type);
638 sigbuffer_add_value (buf, type->type);
639 encode_type (assembly, type->data.type, buf);
641 case MONO_TYPE_SZARRAY:
642 sigbuffer_add_value (buf, type->type);
643 encode_type (assembly, &type->data.klass->byval_arg, buf);
645 case MONO_TYPE_VALUETYPE:
646 case MONO_TYPE_CLASS: {
647 MonoClass *k = mono_class_from_mono_type (type);
649 if (k->generic_container) {
650 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
651 encode_generic_class (assembly, gclass, buf);
654 * Make sure we use the correct type.
656 sigbuffer_add_value (buf, k->byval_arg.type);
658 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
659 * otherwise two typerefs could point to the same type, leading to
660 * verification errors.
662 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
666 case MONO_TYPE_ARRAY:
667 sigbuffer_add_value (buf, type->type);
668 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
669 sigbuffer_add_value (buf, type->data.array->rank);
670 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
671 sigbuffer_add_value (buf, 0);
673 case MONO_TYPE_GENERICINST:
674 encode_generic_class (assembly, type->data.generic_class, buf);
678 sigbuffer_add_value (buf, type->type);
679 sigbuffer_add_value (buf, type->data.generic_param->num);
682 g_error ("need to encode type %x", type->type);
687 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
690 sigbuffer_add_value (buf, MONO_TYPE_VOID);
695 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
696 encode_type (assembly, type->type, buf);
700 g_assert_not_reached ();
705 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
710 for (i = 0; i < mono_array_length (modreq); ++i) {
711 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
712 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
713 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
717 for (i = 0; i < mono_array_length (modopt); ++i) {
718 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
719 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
720 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
726 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
730 guint32 nparams = sig->param_count;
736 sigbuffer_init (&buf, 32);
738 * FIXME: vararg, explicit_this, differenc call_conv values...
740 idx = sig->call_convention;
742 idx |= 0x20; /* hasthis */
743 if (sig->generic_param_count)
744 idx |= 0x10; /* generic */
745 sigbuffer_add_byte (&buf, idx);
746 if (sig->generic_param_count)
747 sigbuffer_add_value (&buf, sig->generic_param_count);
748 sigbuffer_add_value (&buf, nparams);
749 encode_type (assembly, sig->ret, &buf);
750 for (i = 0; i < nparams; ++i) {
751 if (i == sig->sentinelpos)
752 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
753 encode_type (assembly, sig->params [i], &buf);
755 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
756 sigbuffer_free (&buf);
761 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
764 * FIXME: reuse code from method_encode_signature().
768 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
769 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
770 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
773 sigbuffer_init (&buf, 32);
774 /* LAMESPEC: all the call conv spec is foobared */
775 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
776 if (mb->call_conv & 2)
777 idx |= 0x5; /* vararg */
778 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
779 idx |= 0x20; /* hasthis */
781 idx |= 0x10; /* generic */
782 sigbuffer_add_byte (&buf, idx);
784 sigbuffer_add_value (&buf, ngparams);
785 sigbuffer_add_value (&buf, nparams + notypes);
786 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
787 encode_reflection_type (assembly, mb->rtype, &buf);
788 for (i = 0; i < nparams; ++i) {
789 MonoArray *modreq = NULL;
790 MonoArray *modopt = NULL;
791 MonoReflectionType *pt;
793 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
794 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
795 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
796 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
797 encode_custom_modifiers (assembly, modreq, modopt, &buf);
798 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
799 encode_reflection_type (assembly, pt, &buf);
802 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
803 for (i = 0; i < notypes; ++i) {
804 MonoReflectionType *pt;
806 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
807 encode_reflection_type (assembly, pt, &buf);
810 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
811 sigbuffer_free (&buf);
816 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
818 MonoDynamicTable *table;
820 guint32 idx, sig_idx;
821 guint nl = mono_array_length (ilgen->locals);
825 sigbuffer_init (&buf, 32);
826 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
827 idx = table->next_idx ++;
829 alloc_table (table, table->rows);
830 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
832 sigbuffer_add_value (&buf, 0x07);
833 sigbuffer_add_value (&buf, nl);
834 for (i = 0; i < nl; ++i) {
835 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
838 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
840 encode_reflection_type (assembly, lb->type, &buf);
842 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
843 sigbuffer_free (&buf);
845 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
851 method_count_clauses (MonoReflectionILGen *ilgen)
853 guint32 num_clauses = 0;
856 MonoILExceptionInfo *ex_info;
857 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
858 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
859 if (ex_info->handlers)
860 num_clauses += mono_array_length (ex_info->handlers);
868 static MonoExceptionClause*
869 method_encode_clauses (MonoMemPool *mp, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
871 MonoExceptionClause *clauses;
872 MonoExceptionClause *clause;
873 MonoILExceptionInfo *ex_info;
874 MonoILExceptionBlock *ex_block;
875 guint32 finally_start;
876 int i, j, clause_index;;
878 clauses = mp_g_new0 (mp, MonoExceptionClause, num_clauses);
881 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
882 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
883 finally_start = ex_info->start + ex_info->len;
884 if (!ex_info->handlers)
886 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
887 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
888 clause = &(clauses [clause_index]);
890 clause->flags = ex_block->type;
891 clause->try_offset = ex_info->start;
893 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
894 clause->try_len = finally_start - ex_info->start;
896 clause->try_len = ex_info->len;
897 clause->handler_offset = ex_block->start;
898 clause->handler_len = ex_block->len;
899 if (ex_block->extype) {
900 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
902 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
903 clause->data.filter_offset = ex_block->filter_offset;
905 clause->data.filter_offset = 0;
907 finally_start = ex_block->start + ex_block->len;
917 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
923 gint32 num_locals = 0;
924 gint32 num_exception = 0;
927 char fat_header [12];
930 guint32 local_sig = 0;
931 guint32 header_size = 12;
934 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
935 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
939 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
941 code = mb->ilgen->code;
942 code_size = mb->ilgen->code_len;
943 max_stack = mb->ilgen->max_stack;
944 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
945 if (mb->ilgen->ex_handlers)
946 num_exception = method_count_clauses (mb->ilgen);
950 char *name = mono_string_to_utf8 (mb->name);
951 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
952 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
955 mono_raise_exception (exception);
958 code_size = mono_array_length (code);
959 max_stack = 8; /* we probably need to run a verifier on the code... */
962 stream_data_align (&assembly->code);
964 /* check for exceptions, maxstack, locals */
965 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
967 if (code_size < 64 && !(code_size & 1)) {
968 flags = (code_size << 2) | 0x2;
969 } else if (code_size < 32 && (code_size & 1)) {
970 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
974 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
975 /* add to the fixup todo list */
976 if (mb->ilgen && mb->ilgen->num_token_fixups)
977 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
978 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
979 return assembly->text_rva + idx;
983 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
985 * FIXME: need to set also the header size in fat_flags.
986 * (and more sects and init locals flags)
990 fat_flags |= METHOD_HEADER_MORE_SECTS;
992 fat_flags |= METHOD_HEADER_INIT_LOCALS;
993 fat_header [0] = fat_flags;
994 fat_header [1] = (header_size / 4 ) << 4;
995 short_value = GUINT16_TO_LE (max_stack);
996 memcpy (fat_header + 2, &short_value, 2);
997 int_value = GUINT32_TO_LE (code_size);
998 memcpy (fat_header + 4, &int_value, 4);
999 int_value = GUINT32_TO_LE (local_sig);
1000 memcpy (fat_header + 8, &int_value, 4);
1001 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1002 /* add to the fixup todo list */
1003 if (mb->ilgen && mb->ilgen->num_token_fixups)
1004 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1006 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1007 if (num_exception) {
1008 unsigned char sheader [4];
1009 MonoILExceptionInfo * ex_info;
1010 MonoILExceptionBlock * ex_block;
1013 stream_data_align (&assembly->code);
1014 /* always use fat format for now */
1015 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1016 num_exception *= 6 * sizeof (guint32);
1017 num_exception += 4; /* include the size of the header */
1018 sheader [1] = num_exception & 0xff;
1019 sheader [2] = (num_exception >> 8) & 0xff;
1020 sheader [3] = (num_exception >> 16) & 0xff;
1021 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1022 /* fat header, so we are already aligned */
1024 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1025 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1026 if (ex_info->handlers) {
1027 int finally_start = ex_info->start + ex_info->len;
1028 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1030 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1032 val = GUINT32_TO_LE (ex_block->type);
1033 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1035 val = GUINT32_TO_LE (ex_info->start);
1036 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1037 /* need fault, too, probably */
1038 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1039 val = GUINT32_TO_LE (finally_start - ex_info->start);
1041 val = GUINT32_TO_LE (ex_info->len);
1042 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1043 /* handler offset */
1044 val = GUINT32_TO_LE (ex_block->start);
1045 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1047 val = GUINT32_TO_LE (ex_block->len);
1048 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1049 finally_start = ex_block->start + ex_block->len;
1050 if (ex_block->extype) {
1051 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1053 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1054 val = ex_block->filter_offset;
1058 val = GUINT32_TO_LE (val);
1059 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1060 /*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",
1061 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);*/
1064 g_error ("No clauses for ex info block %d", i);
1068 return assembly->text_rva + idx;
1072 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1075 MonoDynamicTable *table;
1078 table = &assembly->tables [table_idx];
1080 g_assert (col < table->columns);
1082 values = table->values + table->columns;
1083 for (i = 1; i <= table->rows; ++i) {
1084 if (values [col] == token)
1086 values += table->columns;
1092 * LOCKING: Acquires the loader lock.
1094 static MonoCustomAttrInfo*
1095 lookup_custom_attr (MonoImage *image, gpointer member)
1097 MonoCustomAttrInfo* res;
1099 mono_loader_lock ();
1100 res = mono_property_hash_lookup (image->property_hash, member, MONO_PROP_DYNAMIC_CATTR);
1101 mono_loader_unlock ();
1106 return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1110 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1112 /* FIXME: Need to do more checks */
1113 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1114 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1116 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1123 static MonoCustomAttrInfo*
1124 mono_custom_attrs_from_builders (MonoMemPool *mp, MonoImage *image, MonoArray *cattrs)
1126 int i, index, count, not_visible;
1127 MonoCustomAttrInfo *ainfo;
1128 MonoReflectionCustomAttr *cattr;
1132 /* FIXME: check in assembly the Run flag is set */
1134 count = mono_array_length (cattrs);
1136 /* Skip nonpublic attributes since MS.NET seems to do the same */
1137 /* FIXME: This needs to be done more globally */
1139 for (i = 0; i < count; ++i) {
1140 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1141 if (!custom_attr_visible (image, cattr))
1144 count -= not_visible;
1146 ainfo = mp_g_malloc0 (mp, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1148 ainfo->image = image;
1149 ainfo->num_attrs = count;
1150 ainfo->cached = mp != NULL;
1152 mono_loader_lock ();
1153 for (i = 0; i < count; ++i) {
1154 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1155 if (custom_attr_visible (image, cattr)) {
1156 unsigned char *saved = mono_mempool_alloc (image->mempool, mono_array_length (cattr->data));
1157 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1158 ainfo->attrs [index].ctor = cattr->ctor->method;
1159 ainfo->attrs [index].data = saved;
1160 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1164 mono_loader_unlock ();
1170 * LOCKING: Acquires the loader lock.
1173 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1175 MonoCustomAttrInfo *ainfo, *tmp;
1177 if (!cattrs || !mono_array_length (cattrs))
1180 ainfo = mono_custom_attrs_from_builders (image->mempool, image, cattrs);
1181 mono_loader_lock ();
1182 tmp = mono_property_hash_lookup (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR);
1184 mono_custom_attrs_free (tmp);
1185 mono_property_hash_insert (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1186 mono_loader_unlock ();
1190 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1197 * idx is the table index of the object
1198 * type is one of MONO_CUSTOM_ATTR_*
1201 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1203 MonoDynamicTable *table;
1204 MonoReflectionCustomAttr *cattr;
1206 guint32 count, i, token;
1208 char *p = blob_size;
1210 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1213 count = mono_array_length (cattrs);
1214 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1215 table->rows += count;
1216 alloc_table (table, table->rows);
1217 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1218 idx <<= MONO_CUSTOM_ATTR_BITS;
1220 for (i = 0; i < count; ++i) {
1221 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1222 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1223 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1224 type = mono_metadata_token_index (token);
1225 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1226 switch (mono_metadata_token_table (token)) {
1227 case MONO_TABLE_METHOD:
1228 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1230 case MONO_TABLE_MEMBERREF:
1231 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1234 g_warning ("got wrong token in custom attr");
1237 values [MONO_CUSTOM_ATTR_TYPE] = type;
1239 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1240 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1241 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1242 values += MONO_CUSTOM_ATTR_SIZE;
1248 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1250 MonoDynamicTable *table;
1252 guint32 count, i, idx;
1253 MonoReflectionPermissionSet *perm;
1258 count = mono_array_length (permissions);
1259 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1260 table->rows += count;
1261 alloc_table (table, table->rows);
1263 for (i = 0; i < mono_array_length (permissions); ++i) {
1264 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1266 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1268 idx = mono_metadata_token_index (parent_token);
1269 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1270 switch (mono_metadata_token_table (parent_token)) {
1271 case MONO_TABLE_TYPEDEF:
1272 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1274 case MONO_TABLE_METHOD:
1275 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1277 case MONO_TABLE_ASSEMBLY:
1278 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1281 g_assert_not_reached ();
1284 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1285 values [MONO_DECL_SECURITY_PARENT] = idx;
1286 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1293 * Fill in the MethodDef and ParamDef tables for a method.
1294 * This is used for both normal methods and constructors.
1297 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1299 MonoDynamicTable *table;
1303 /* room in this table is already allocated */
1304 table = &assembly->tables [MONO_TABLE_METHOD];
1305 *mb->table_idx = table->next_idx ++;
1306 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1307 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1308 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1309 values [MONO_METHOD_FLAGS] = mb->attrs;
1310 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1311 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1312 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1314 table = &assembly->tables [MONO_TABLE_PARAM];
1315 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1317 mono_image_add_decl_security (assembly,
1318 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1321 MonoDynamicTable *mtable;
1324 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1325 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1328 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1329 if (mono_array_get (mb->pinfo, gpointer, i))
1332 table->rows += count;
1333 alloc_table (table, table->rows);
1334 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1335 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1336 MonoReflectionParamBuilder *pb;
1337 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1338 values [MONO_PARAM_FLAGS] = pb->attrs;
1339 values [MONO_PARAM_SEQUENCE] = i;
1340 if (pb->name != NULL) {
1341 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1343 values [MONO_PARAM_NAME] = 0;
1345 values += MONO_PARAM_SIZE;
1346 if (pb->marshal_info) {
1348 alloc_table (mtable, mtable->rows);
1349 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1350 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1351 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1353 pb->table_idx = table->next_idx++;
1354 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1355 guint32 field_type = 0;
1356 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1358 alloc_table (mtable, mtable->rows);
1359 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1360 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1361 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1362 mvalues [MONO_CONSTANT_TYPE] = field_type;
1363 mvalues [MONO_CONSTANT_PADDING] = 0;
1371 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1373 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1375 rmb->ilgen = mb->ilgen;
1376 rmb->rtype = mb->rtype;
1377 rmb->parameters = mb->parameters;
1378 rmb->generic_params = mb->generic_params;
1379 rmb->generic_container = mb->generic_container;
1380 rmb->opt_types = NULL;
1381 rmb->pinfo = mb->pinfo;
1382 rmb->attrs = mb->attrs;
1383 rmb->iattrs = mb->iattrs;
1384 rmb->call_conv = mb->call_conv;
1385 rmb->code = mb->code;
1386 rmb->type = mb->type;
1387 rmb->name = mb->name;
1388 rmb->table_idx = &mb->table_idx;
1389 rmb->init_locals = mb->init_locals;
1390 rmb->skip_visibility = FALSE;
1391 rmb->return_modreq = mb->return_modreq;
1392 rmb->return_modopt = mb->return_modopt;
1393 rmb->param_modreq = mb->param_modreq;
1394 rmb->param_modopt = mb->param_modopt;
1395 rmb->permissions = mb->permissions;
1396 rmb->mhandle = mb->mhandle;
1401 rmb->charset = mb->charset;
1402 rmb->extra_flags = mb->extra_flags;
1403 rmb->native_cc = mb->native_cc;
1404 rmb->dllentry = mb->dllentry;
1410 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1412 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1414 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1416 rmb->ilgen = mb->ilgen;
1417 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1418 rmb->parameters = mb->parameters;
1419 rmb->generic_params = NULL;
1420 rmb->generic_container = NULL;
1421 rmb->opt_types = NULL;
1422 rmb->pinfo = mb->pinfo;
1423 rmb->attrs = mb->attrs;
1424 rmb->iattrs = mb->iattrs;
1425 rmb->call_conv = mb->call_conv;
1427 rmb->type = mb->type;
1428 rmb->name = mono_string_new (mono_domain_get (), name);
1429 rmb->table_idx = &mb->table_idx;
1430 rmb->init_locals = mb->init_locals;
1431 rmb->skip_visibility = FALSE;
1432 rmb->return_modreq = NULL;
1433 rmb->return_modopt = NULL;
1434 rmb->param_modreq = mb->param_modreq;
1435 rmb->param_modopt = mb->param_modopt;
1436 rmb->permissions = mb->permissions;
1437 rmb->mhandle = mb->mhandle;
1443 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1445 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1447 rmb->ilgen = mb->ilgen;
1448 rmb->rtype = mb->rtype;
1449 rmb->parameters = mb->parameters;
1450 rmb->generic_params = NULL;
1451 rmb->generic_container = NULL;
1452 rmb->opt_types = NULL;
1454 rmb->attrs = mb->attrs;
1456 rmb->call_conv = mb->call_conv;
1458 rmb->type = (MonoObject *) mb->owner;
1459 rmb->name = mb->name;
1460 rmb->table_idx = NULL;
1461 rmb->init_locals = mb->init_locals;
1462 rmb->skip_visibility = mb->skip_visibility;
1463 rmb->return_modreq = NULL;
1464 rmb->return_modopt = NULL;
1465 rmb->param_modreq = NULL;
1466 rmb->param_modopt = NULL;
1467 rmb->permissions = NULL;
1468 rmb->mhandle = mb->mhandle;
1474 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1476 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1477 MonoDynamicTable *table;
1481 if (!mb->override_method)
1484 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1486 alloc_table (table, table->rows);
1487 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1488 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1489 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1491 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1492 switch (mono_metadata_token_table (tok)) {
1493 case MONO_TABLE_MEMBERREF:
1494 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1496 case MONO_TABLE_METHOD:
1497 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1500 g_assert_not_reached ();
1502 values [MONO_METHODIMPL_DECLARATION] = tok;
1506 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1508 MonoDynamicTable *table;
1510 ReflectionMethodBuilder rmb;
1513 reflection_methodbuilder_from_method_builder (&rmb, mb);
1515 mono_image_basic_method (&rmb, assembly);
1516 mb->table_idx = *rmb.table_idx;
1518 if (mb->dll) { /* It's a P/Invoke method */
1520 /* map CharSet values to on-disk values */
1521 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1522 int extra_flags = mb->extra_flags;
1523 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1525 alloc_table (table, table->rows);
1526 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1528 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1529 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1531 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1533 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1534 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1535 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1536 table = &assembly->tables [MONO_TABLE_MODULEREF];
1538 alloc_table (table, table->rows);
1539 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1540 values [MONO_IMPLMAP_SCOPE] = table->rows;
1544 if (mb->generic_params) {
1545 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1546 table->rows += mono_array_length (mb->generic_params);
1547 alloc_table (table, table->rows);
1548 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1549 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1551 mono_image_get_generic_param_info (
1552 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1559 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1561 ReflectionMethodBuilder rmb;
1563 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1565 mono_image_basic_method (&rmb, assembly);
1566 mb->table_idx = *rmb.table_idx;
1570 type_get_fully_qualified_name (MonoType *type)
1572 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1576 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1580 klass = my_mono_class_from_mono_type (type);
1582 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1583 ta = klass->image->assembly;
1584 if (ta->dynamic || (ta == ass)) {
1585 if (klass->generic_class || klass->generic_container)
1586 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1587 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1589 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1592 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1596 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1601 if (!assembly->save)
1604 sigbuffer_init (&buf, 32);
1606 sigbuffer_add_value (&buf, 0x06);
1607 /* encode custom attributes before the type */
1608 /* FIXME: This should probably go in encode_type () */
1609 if (type->num_mods) {
1610 for (i = 0; i < type->num_mods; ++i) {
1611 if (type->modifiers [i].required)
1612 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1614 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1615 sigbuffer_add_value (&buf, type->modifiers [i].token);
1618 encode_type (assembly, type, &buf);
1619 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1620 sigbuffer_free (&buf);
1625 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1630 sigbuffer_init (&buf, 32);
1632 sigbuffer_add_value (&buf, 0x06);
1633 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1634 /* encode custom attributes before the type */
1635 encode_reflection_type (assembly, fb->type, &buf);
1636 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1637 sigbuffer_free (&buf);
1642 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1643 char blob_size [64];
1644 char *b = blob_size;
1647 guint32 idx = 0, len = 0, dummy = 0;
1649 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1650 guint32 fpa_double [2];
1655 p = buf = g_malloc (64);
1657 *ret_type = MONO_TYPE_CLASS;
1659 box_val = (char*)&dummy;
1661 box_val = ((char*)val) + sizeof (MonoObject);
1662 *ret_type = val->vtable->klass->byval_arg.type;
1665 switch (*ret_type) {
1666 case MONO_TYPE_BOOLEAN:
1671 case MONO_TYPE_CHAR:
1688 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1689 fpa_p = (guint32*)box_val;
1690 fpa_double [0] = fpa_p [1];
1691 fpa_double [1] = fpa_p [0];
1692 box_val = (char*)fpa_double;
1696 case MONO_TYPE_VALUETYPE:
1697 if (val->vtable->klass->enumtype) {
1698 *ret_type = val->vtable->klass->enum_basetype->type;
1701 g_error ("we can't encode valuetypes");
1702 case MONO_TYPE_CLASS:
1704 case MONO_TYPE_STRING: {
1705 MonoString *str = (MonoString*)val;
1706 /* there is no signature */
1707 len = str->length * 2;
1708 mono_metadata_encode_value (len, b, &b);
1709 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1711 char *swapped = g_malloc (2 * mono_string_length (str));
1712 const char *p = (const char*)mono_string_chars (str);
1714 swap_with_size (swapped, p, 2, mono_string_length (str));
1715 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1719 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1725 case MONO_TYPE_GENERICINST:
1726 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1729 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1732 /* there is no signature */
1733 mono_metadata_encode_value (len, b, &b);
1734 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1735 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1736 swap_with_size (blob_size, box_val, len, 1);
1737 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1739 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1747 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1752 sigbuffer_init (&buf, 32);
1754 sigbuffer_add_value (&buf, minfo->type);
1756 switch (minfo->type) {
1757 case MONO_NATIVE_BYVALTSTR:
1758 case MONO_NATIVE_BYVALARRAY:
1759 sigbuffer_add_value (&buf, minfo->count);
1761 case MONO_NATIVE_LPARRAY:
1762 if (minfo->eltype || minfo->has_size) {
1763 sigbuffer_add_value (&buf, minfo->eltype);
1764 if (minfo->has_size) {
1765 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1766 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1768 /* LAMESPEC: ElemMult is undocumented */
1769 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1773 case MONO_NATIVE_CUSTOM:
1775 str = mono_string_to_utf8 (minfo->guid);
1777 sigbuffer_add_value (&buf, len);
1778 sigbuffer_add_mem (&buf, str, len);
1781 sigbuffer_add_value (&buf, 0);
1783 /* native type name */
1784 sigbuffer_add_value (&buf, 0);
1785 /* custom marshaler type name */
1786 if (minfo->marshaltype || minfo->marshaltyperef) {
1787 if (minfo->marshaltyperef)
1788 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1790 str = mono_string_to_utf8 (minfo->marshaltype);
1792 sigbuffer_add_value (&buf, len);
1793 sigbuffer_add_mem (&buf, str, len);
1796 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1797 sigbuffer_add_value (&buf, 0);
1799 if (minfo->mcookie) {
1800 str = mono_string_to_utf8 (minfo->mcookie);
1802 sigbuffer_add_value (&buf, len);
1803 sigbuffer_add_mem (&buf, str, len);
1806 sigbuffer_add_value (&buf, 0);
1812 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1813 sigbuffer_free (&buf);
1818 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1820 MonoDynamicTable *table;
1823 /* maybe this fixup should be done in the C# code */
1824 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1825 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1826 table = &assembly->tables [MONO_TABLE_FIELD];
1827 fb->table_idx = table->next_idx ++;
1828 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1829 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1830 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1831 values [MONO_FIELD_FLAGS] = fb->attrs;
1832 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1834 if (fb->offset != -1) {
1835 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1837 alloc_table (table, table->rows);
1838 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1839 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1840 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1842 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1843 guint32 field_type = 0;
1844 table = &assembly->tables [MONO_TABLE_CONSTANT];
1846 alloc_table (table, table->rows);
1847 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1848 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1849 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1850 values [MONO_CONSTANT_TYPE] = field_type;
1851 values [MONO_CONSTANT_PADDING] = 0;
1853 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1855 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1857 alloc_table (table, table->rows);
1858 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1859 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1861 * We store it in the code section because it's simpler for now.
1864 if (mono_array_length (fb->rva_data) >= 10)
1865 stream_data_align (&assembly->code);
1866 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1868 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1869 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1871 if (fb->marshal_info) {
1872 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1874 alloc_table (table, table->rows);
1875 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1876 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1877 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1882 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1885 guint32 nparams = 0;
1886 MonoReflectionMethodBuilder *mb = fb->get_method;
1887 MonoReflectionMethodBuilder *smb = fb->set_method;
1890 if (mb && mb->parameters)
1891 nparams = mono_array_length (mb->parameters);
1892 if (!mb && smb && smb->parameters)
1893 nparams = mono_array_length (smb->parameters) - 1;
1894 sigbuffer_init (&buf, 32);
1895 sigbuffer_add_byte (&buf, 0x08);
1896 sigbuffer_add_value (&buf, nparams);
1898 encode_reflection_type (assembly, mb->rtype, &buf);
1899 for (i = 0; i < nparams; ++i) {
1900 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1901 encode_reflection_type (assembly, pt, &buf);
1903 } else if (smb && smb->parameters) {
1904 /* the property type is the last param */
1905 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1906 for (i = 0; i < nparams; ++i) {
1907 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1908 encode_reflection_type (assembly, pt, &buf);
1911 encode_reflection_type (assembly, fb->type, &buf);
1914 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1915 sigbuffer_free (&buf);
1920 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1922 MonoDynamicTable *table;
1924 guint num_methods = 0;
1928 * we need to set things in the following tables:
1929 * PROPERTYMAP (info already filled in _get_type_info ())
1930 * PROPERTY (rows already preallocated in _get_type_info ())
1931 * METHOD (method info already done with the generic method code)
1934 table = &assembly->tables [MONO_TABLE_PROPERTY];
1935 pb->table_idx = table->next_idx ++;
1936 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1937 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1938 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1939 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1941 /* FIXME: we still don't handle 'other' methods */
1942 if (pb->get_method) num_methods ++;
1943 if (pb->set_method) num_methods ++;
1945 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1946 table->rows += num_methods;
1947 alloc_table (table, table->rows);
1949 if (pb->get_method) {
1950 semaidx = table->next_idx ++;
1951 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1952 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1953 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1954 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1956 if (pb->set_method) {
1957 semaidx = table->next_idx ++;
1958 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1959 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1960 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1961 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1966 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1968 MonoDynamicTable *table;
1970 guint num_methods = 0;
1974 * we need to set things in the following tables:
1975 * EVENTMAP (info already filled in _get_type_info ())
1976 * EVENT (rows already preallocated in _get_type_info ())
1977 * METHOD (method info already done with the generic method code)
1980 table = &assembly->tables [MONO_TABLE_EVENT];
1981 eb->table_idx = table->next_idx ++;
1982 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1983 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1984 values [MONO_EVENT_FLAGS] = eb->attrs;
1985 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1988 * FIXME: we still don't handle 'other' methods
1990 if (eb->add_method) num_methods ++;
1991 if (eb->remove_method) num_methods ++;
1992 if (eb->raise_method) num_methods ++;
1994 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1995 table->rows += num_methods;
1996 alloc_table (table, table->rows);
1998 if (eb->add_method) {
1999 semaidx = table->next_idx ++;
2000 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2001 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2002 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2003 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2005 if (eb->remove_method) {
2006 semaidx = table->next_idx ++;
2007 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2008 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2009 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2010 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2012 if (eb->raise_method) {
2013 semaidx = table->next_idx ++;
2014 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2015 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2016 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2017 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2022 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2024 MonoDynamicTable *table;
2025 guint32 num_constraints, i;
2029 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2030 num_constraints = gparam->iface_constraints ?
2031 mono_array_length (gparam->iface_constraints) : 0;
2032 table->rows += num_constraints;
2033 if (gparam->base_type)
2035 alloc_table (table, table->rows);
2037 if (gparam->base_type) {
2038 table_idx = table->next_idx ++;
2039 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2041 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2042 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2043 assembly, gparam->base_type->type);
2046 for (i = 0; i < num_constraints; i++) {
2047 MonoReflectionType *constraint = mono_array_get (
2048 gparam->iface_constraints, gpointer, i);
2050 table_idx = table->next_idx ++;
2051 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2053 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2054 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2055 assembly, constraint->type);
2060 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2062 GenericParamTableEntry *entry;
2065 * The GenericParam table must be sorted according to the `owner' field.
2066 * We need to do this sorting prior to writing the GenericParamConstraint
2067 * table, since we have to use the final GenericParam table indices there
2068 * and they must also be sorted.
2071 entry = g_new0 (GenericParamTableEntry, 1);
2072 entry->owner = owner;
2074 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2075 MONO_GC_REGISTER_ROOT (entry->gparam);
2077 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2079 g_ptr_array_add (assembly->gen_params, entry);
2083 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2085 MonoDynamicTable *table;
2086 MonoGenericParam *param;
2090 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2091 table_idx = table->next_idx ++;
2092 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2094 param = entry->gparam->type.type->data.generic_param;
2096 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2097 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2098 values [MONO_GENERICPARAM_NUMBER] = param->num;
2099 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2101 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2103 encode_constraints (entry->gparam, table_idx, assembly);
2107 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2109 MonoDynamicTable *table;
2112 guint32 cols [MONO_ASSEMBLY_SIZE];
2116 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2119 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2120 table = &assembly->tables [MONO_TABLE_MODULEREF];
2121 token = table->next_idx ++;
2123 alloc_table (table, table->rows);
2124 values = table->values + token * MONO_MODULEREF_SIZE;
2125 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2127 token <<= MONO_RESOLTION_SCOPE_BITS;
2128 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2129 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2134 if (image->assembly->dynamic)
2136 memset (cols, 0, sizeof (cols));
2138 /* image->assembly->image is the manifest module */
2139 image = image->assembly->image;
2140 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2143 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2144 token = table->next_idx ++;
2146 alloc_table (table, table->rows);
2147 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2148 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2149 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2150 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2151 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2152 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2153 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2154 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2155 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2157 if (strcmp ("", image->assembly->aname.culture)) {
2158 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2159 image->assembly->aname.culture);
2162 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2163 guchar pubtoken [9];
2165 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2166 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2168 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2170 token <<= MONO_RESOLTION_SCOPE_BITS;
2171 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2172 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2177 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2179 MonoDynamicTable *table;
2184 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2187 sigbuffer_init (&buf, 32);
2188 switch (type->type) {
2189 case MONO_TYPE_FNPTR:
2191 case MONO_TYPE_SZARRAY:
2192 case MONO_TYPE_ARRAY:
2194 case MONO_TYPE_MVAR:
2195 case MONO_TYPE_GENERICINST:
2196 encode_type (assembly, type, &buf);
2198 case MONO_TYPE_CLASS:
2199 case MONO_TYPE_VALUETYPE: {
2200 MonoClass *k = mono_class_from_mono_type (type);
2201 if (!k || !k->generic_container) {
2202 sigbuffer_free (&buf);
2205 encode_type (assembly, type, &buf);
2209 sigbuffer_free (&buf);
2213 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2214 if (assembly->save) {
2215 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2216 alloc_table (table, table->rows + 1);
2217 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2218 values [MONO_TYPESPEC_SIGNATURE] = token;
2220 sigbuffer_free (&buf);
2222 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2223 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2229 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2231 MonoDynamicTable *table;
2233 guint32 token, scope, enclosing;
2236 /* if the type requires a typespec, we must try that first*/
2237 if (try_typespec && (token = create_typespec (assembly, type)))
2239 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2242 klass = my_mono_class_from_mono_type (type);
2244 klass = mono_class_from_mono_type (type);
2247 * If it's in the same module and not a generic type parameter:
2249 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2250 (type->type != MONO_TYPE_MVAR)) {
2251 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2252 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2253 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2257 if (klass->nested_in) {
2258 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2259 /* get the typeref idx of the enclosing type */
2260 enclosing >>= MONO_TYPEDEFORREF_BITS;
2261 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2263 scope = resolution_scope_from_image (assembly, klass->image);
2265 table = &assembly->tables [MONO_TABLE_TYPEREF];
2266 if (assembly->save) {
2267 alloc_table (table, table->rows + 1);
2268 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2269 values [MONO_TYPEREF_SCOPE] = scope;
2270 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2271 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2273 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2274 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2276 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2281 * Despite the name, we handle also TypeSpec (with the above helper).
2284 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2286 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2290 * Insert a memberef row into the metadata: the token that point to the memberref
2291 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2292 * mono_image_get_fieldref_token()).
2293 * The sig param is an index to an already built signature.
2296 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2298 MonoDynamicTable *table;
2300 guint32 token, pclass;
2303 parent = mono_image_typedef_or_ref (assembly, type);
2304 switch (parent & MONO_TYPEDEFORREF_MASK) {
2305 case MONO_TYPEDEFORREF_TYPEREF:
2306 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2308 case MONO_TYPEDEFORREF_TYPESPEC:
2309 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2311 case MONO_TYPEDEFORREF_TYPEDEF:
2312 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2315 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2318 /* extract the index */
2319 parent >>= MONO_TYPEDEFORREF_BITS;
2321 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2323 if (assembly->save) {
2324 alloc_table (table, table->rows + 1);
2325 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2326 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2327 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2328 values [MONO_MEMBERREF_SIGNATURE] = sig;
2331 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2338 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2341 MonoMethodSignature *sig;
2343 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2348 * A methodref signature can't contain an unmanaged calling convention.
2350 sig = mono_metadata_signature_dup (mono_method_signature (method));
2351 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2352 sig->call_convention = MONO_CALL_DEFAULT;
2353 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2354 method->name, method_encode_signature (assembly, sig));
2356 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2361 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2364 ReflectionMethodBuilder rmb;
2367 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2371 name = mono_string_to_utf8 (method->name);
2372 reflection_methodbuilder_from_method_builder (&rmb, method);
2375 * A methodref signature can't contain an unmanaged calling convention.
2376 * Since some flags are encoded as part of call_conv, we need to check against it.
2378 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2379 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2380 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2381 name, method_builder_encode_signature (assembly, &rmb));
2384 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2389 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2390 const gchar *name, guint32 sig)
2392 MonoDynamicTable *table;
2396 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2398 if (assembly->save) {
2399 alloc_table (table, table->rows + 1);
2400 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2401 values [MONO_MEMBERREF_CLASS] = original;
2402 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2403 values [MONO_MEMBERREF_SIGNATURE] = sig;
2406 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2413 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2417 guint32 nparams = mono_array_length (mb->generic_params);
2420 if (!assembly->save)
2423 sigbuffer_init (&buf, 32);
2425 sigbuffer_add_value (&buf, 0xa);
2426 sigbuffer_add_value (&buf, nparams);
2428 for (i = 0; i < nparams; i++) {
2429 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2430 sigbuffer_add_value (&buf, i);
2433 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2434 sigbuffer_free (&buf);
2439 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2441 MonoDynamicTable *table;
2443 guint32 token, mtoken = 0;
2445 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2449 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2451 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2452 switch (mono_metadata_token_table (mtoken)) {
2453 case MONO_TABLE_MEMBERREF:
2454 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2456 case MONO_TABLE_METHOD:
2457 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2460 g_assert_not_reached ();
2463 if (assembly->save) {
2464 alloc_table (table, table->rows + 1);
2465 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2466 values [MONO_METHODSPEC_METHOD] = mtoken;
2467 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2470 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2473 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2478 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2482 if (mb->generic_params && create_methodspec)
2483 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2485 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2489 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2490 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2495 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2498 ReflectionMethodBuilder rmb;
2501 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2505 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2507 name = mono_string_to_utf8 (rmb.name);
2508 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2509 name, method_builder_encode_signature (assembly, &rmb));
2512 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2517 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2522 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2525 g_assert (f->field->parent);
2526 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2527 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2528 f->field->name, fieldref_encode_signature (assembly, type));
2529 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2534 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2538 MonoGenericClass *gclass;
2539 MonoDynamicGenericClass *dgclass;
2540 MonoReflectionFieldBuilder *fb = f->fb;
2543 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2546 klass = mono_class_from_mono_type (f->inst->type.type);
2547 gclass = f->inst->type.type->data.generic_class;
2548 g_assert (gclass->is_dynamic);
2549 dgclass = (MonoDynamicGenericClass *) gclass;
2551 name = mono_string_to_utf8 (fb->name);
2552 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2553 field_encode_signature (assembly, fb));
2555 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2560 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2564 MonoGenericClass *gclass;
2565 MonoDynamicGenericClass *dgclass;
2566 MonoReflectionCtorBuilder *cb = c->cb;
2567 ReflectionMethodBuilder rmb;
2570 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2572 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2575 klass = mono_class_from_mono_type (c->inst->type.type);
2576 gclass = c->inst->type.type->data.generic_class;
2577 g_assert (gclass->is_dynamic);
2578 dgclass = (MonoDynamicGenericClass *) gclass;
2580 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2582 name = mono_string_to_utf8 (rmb.name);
2584 sig = method_builder_encode_signature (assembly, &rmb);
2586 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2589 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2594 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2598 MonoGenericClass *gclass;
2599 MonoReflectionMethodBuilder *mb = m->mb;
2600 ReflectionMethodBuilder rmb;
2603 if (create_methodspec && mb->generic_params)
2605 g_assert_not_reached ();
2607 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2610 klass = mono_class_from_mono_type (m->inst->type.type);
2611 gclass = m->inst->type.type->data.generic_class;
2612 g_assert (gclass->is_dynamic);
2614 reflection_methodbuilder_from_method_builder (&rmb, mb);
2616 name = mono_string_to_utf8 (rmb.name);
2618 sig = method_builder_encode_signature (assembly, &rmb);
2620 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2623 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2628 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2632 guint32 nparams = context->method_inst->type_argc;
2635 if (!assembly->save)
2638 sigbuffer_init (&buf, 32);
2640 * FIXME: vararg, explicit_this, differenc call_conv values...
2642 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2643 sigbuffer_add_value (&buf, nparams);
2645 for (i = 0; i < nparams; i++)
2646 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2648 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2649 sigbuffer_free (&buf);
2654 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2656 MonoDynamicTable *table;
2658 guint32 token, mtoken = 0, sig;
2659 MonoMethodInflated *imethod;
2660 MonoMethod *declaring;
2662 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2664 g_assert (method->is_inflated);
2665 imethod = (MonoMethodInflated *) method;
2666 declaring = imethod->declaring;
2668 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2669 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2671 if (!mono_method_signature (declaring)->generic_param_count)
2674 switch (mono_metadata_token_table (mtoken)) {
2675 case MONO_TABLE_MEMBERREF:
2676 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2678 case MONO_TABLE_METHOD:
2679 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2682 g_assert_not_reached ();
2685 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2687 if (assembly->save) {
2688 alloc_table (table, table->rows + 1);
2689 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2690 values [MONO_METHODSPEC_METHOD] = mtoken;
2691 values [MONO_METHODSPEC_SIGNATURE] = sig;
2694 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2701 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2703 MonoMethodInflated *imethod;
2706 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2710 g_assert (method->is_inflated);
2711 imethod = (MonoMethodInflated *) method;
2713 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2714 token = method_encode_methodspec (assembly, method);
2716 guint32 sig = method_encode_signature (
2717 assembly, mono_method_signature (imethod->declaring));
2718 token = mono_image_get_memberref_token (
2719 assembly, &method->klass->byval_arg, method->name, sig);
2722 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2727 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2729 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2732 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2733 token = mono_image_get_memberref_token (
2734 assembly, &m->klass->byval_arg, m->name, sig);
2740 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2742 MonoDynamicTable *table;
2750 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2751 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2752 * Because of this, we must not insert it into the `typeref' hash table.
2755 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2759 sigbuffer_init (&buf, 32);
2761 g_assert (tb->generic_params);
2762 klass = mono_class_from_mono_type (tb->type.type);
2764 if (tb->generic_container)
2765 mono_reflection_create_generic_class (tb);
2767 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2768 g_assert (klass->generic_container);
2769 sigbuffer_add_value (&buf, klass->byval_arg.type);
2770 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2772 count = mono_array_length (tb->generic_params);
2773 sigbuffer_add_value (&buf, count);
2774 for (i = 0; i < count; i++) {
2775 MonoReflectionGenericParam *gparam;
2777 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2779 encode_type (assembly, gparam->type.type, &buf);
2782 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2784 if (assembly->save) {
2785 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2786 alloc_table (table, table->rows + 1);
2787 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2788 values [MONO_TYPESPEC_SIGNATURE] = token;
2790 sigbuffer_free (&buf);
2792 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2793 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2799 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2802 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2804 int i, count, len, pos;
2809 count += mono_array_length (modreq);
2811 count += mono_array_length (modopt);
2814 return mono_metadata_type_dup (NULL, type);
2816 len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
2818 memcpy (t, type, len);
2820 t->num_mods = count;
2823 for (i = 0; i < mono_array_length (modreq); ++i) {
2824 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
2825 t->modifiers [pos].required = 1;
2826 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2831 for (i = 0; i < mono_array_length (modopt); ++i) {
2832 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
2833 t->modifiers [pos].required = 0;
2834 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2843 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2845 MonoDynamicTable *table;
2847 MonoType *custom = NULL;
2849 guint32 token, pclass, parent, sig;
2852 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2856 klass = mono_class_from_mono_type (fb->typeb->type);
2857 name = mono_string_to_utf8 (fb->name);
2859 /* fb->type does not include the custom modifiers */
2860 /* FIXME: We should do this in one place when a fieldbuilder is created */
2861 if (fb->modreq || fb->modopt) {
2862 custom = add_custom_modifiers (assembly, fb->type->type, fb->modreq, fb->modopt);
2863 sig = fieldref_encode_signature (assembly, custom);
2866 sig = fieldref_encode_signature (assembly, fb->type->type);
2869 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2870 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2872 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2873 parent >>= MONO_TYPEDEFORREF_BITS;
2875 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2877 if (assembly->save) {
2878 alloc_table (table, table->rows + 1);
2879 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2880 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2881 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2882 values [MONO_MEMBERREF_SIGNATURE] = sig;
2885 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2887 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2893 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2900 if (!assembly->save)
2903 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2904 g_assert (helper->type == 2);
2906 if (helper->arguments)
2907 nargs = mono_array_length (helper->arguments);
2911 size = 10 + (nargs * 10);
2913 sigbuffer_init (&buf, 32);
2915 /* Encode calling convention */
2916 /* Change Any to Standard */
2917 if ((helper->call_conv & 0x03) == 0x03)
2918 helper->call_conv = 0x01;
2919 /* explicit_this implies has_this */
2920 if (helper->call_conv & 0x40)
2921 helper->call_conv &= 0x20;
2923 if (helper->call_conv == 0) { /* Unmanaged */
2924 idx = helper->unmanaged_call_conv - 1;
2927 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2928 if (helper->call_conv & 0x02) /* varargs */
2932 sigbuffer_add_byte (&buf, idx);
2933 sigbuffer_add_value (&buf, nargs);
2934 encode_reflection_type (assembly, helper->return_type, &buf);
2935 for (i = 0; i < nargs; ++i) {
2936 MonoArray *modreqs = NULL;
2937 MonoArray *modopts = NULL;
2938 MonoReflectionType *pt;
2940 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
2941 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
2942 if (helper->modopts && (i < mono_array_length (helper->modopts)))
2943 modopts = mono_array_get (helper->modopts, MonoArray*, i);
2945 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
2946 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2947 encode_reflection_type (assembly, pt, &buf);
2949 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2950 sigbuffer_free (&buf);
2956 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2959 MonoDynamicTable *table;
2962 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2963 idx = table->next_idx ++;
2965 alloc_table (table, table->rows);
2966 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2968 values [MONO_STAND_ALONE_SIGNATURE] =
2969 mono_reflection_encode_sighelper (assembly, helper);
2975 reflection_cc_to_file (int call_conv) {
2976 switch (call_conv & 0x3) {
2978 case 1: return MONO_CALL_DEFAULT;
2979 case 2: return MONO_CALL_VARARG;
2981 g_assert_not_reached ();
2988 MonoMethodSignature *sig;
2994 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2999 MonoMethodSignature *sig;
3002 name = mono_string_to_utf8 (m->name);
3003 nparams = mono_array_length (m->parameters);
3004 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
3006 sig->sentinelpos = -1;
3007 sig->call_convention = reflection_cc_to_file (m->call_conv);
3008 sig->param_count = nparams;
3009 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
3010 for (i = 0; i < nparams; ++i) {
3011 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
3012 sig->params [i] = t->type;
3015 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3017 if (strcmp (name, am->name) == 0 &&
3018 mono_metadata_type_equal (am->parent, m->parent->type) &&
3019 mono_metadata_signature_equal (am->sig, sig)) {
3022 m->table_idx = am->token & 0xffffff;
3026 am = g_new0 (ArrayMethod, 1);
3029 am->parent = m->parent->type;
3030 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3031 method_encode_signature (assembly, sig));
3032 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3033 m->table_idx = am->token & 0xffffff;
3038 * Insert into the metadata tables all the info about the TypeBuilder tb.
3039 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3042 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3044 MonoDynamicTable *table;
3046 int i, is_object = 0, is_system = 0;
3049 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3050 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3051 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3052 n = mono_string_to_utf8 (tb->name);
3053 if (strcmp (n, "Object") == 0)
3055 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3057 n = mono_string_to_utf8 (tb->nspace);
3058 if (strcmp (n, "System") == 0)
3060 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3062 if (tb->parent && !(is_system && is_object) &&
3063 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3064 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
3066 values [MONO_TYPEDEF_EXTENDS] = 0;
3068 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3069 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3072 * if we have explicitlayout or sequentiallayouts, output data in the
3073 * ClassLayout table.
3075 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3076 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3077 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3079 alloc_table (table, table->rows);
3080 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3081 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3082 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3083 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3086 /* handle interfaces */
3087 if (tb->interfaces) {
3088 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3090 table->rows += mono_array_length (tb->interfaces);
3091 alloc_table (table, table->rows);
3092 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3093 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3094 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3095 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3096 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3097 values += MONO_INTERFACEIMPL_SIZE;
3103 table = &assembly->tables [MONO_TABLE_FIELD];
3104 table->rows += tb->num_fields;
3105 alloc_table (table, table->rows);
3106 for (i = 0; i < tb->num_fields; ++i)
3107 mono_image_get_field_info (
3108 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3111 /* handle constructors */
3113 table = &assembly->tables [MONO_TABLE_METHOD];
3114 table->rows += mono_array_length (tb->ctors);
3115 alloc_table (table, table->rows);
3116 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3117 mono_image_get_ctor_info (domain,
3118 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3121 /* handle methods */
3123 table = &assembly->tables [MONO_TABLE_METHOD];
3124 table->rows += tb->num_methods;
3125 alloc_table (table, table->rows);
3126 for (i = 0; i < tb->num_methods; ++i)
3127 mono_image_get_method_info (
3128 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3131 /* Do the same with properties etc.. */
3132 if (tb->events && mono_array_length (tb->events)) {
3133 table = &assembly->tables [MONO_TABLE_EVENT];
3134 table->rows += mono_array_length (tb->events);
3135 alloc_table (table, table->rows);
3136 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3138 alloc_table (table, table->rows);
3139 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3140 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3141 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3142 for (i = 0; i < mono_array_length (tb->events); ++i)
3143 mono_image_get_event_info (
3144 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3146 if (tb->properties && mono_array_length (tb->properties)) {
3147 table = &assembly->tables [MONO_TABLE_PROPERTY];
3148 table->rows += mono_array_length (tb->properties);
3149 alloc_table (table, table->rows);
3150 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3152 alloc_table (table, table->rows);
3153 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3154 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3155 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3156 for (i = 0; i < mono_array_length (tb->properties); ++i)
3157 mono_image_get_property_info (
3158 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3161 /* handle generic parameters */
3162 if (tb->generic_params) {
3163 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3164 table->rows += mono_array_length (tb->generic_params);
3165 alloc_table (table, table->rows);
3166 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3167 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3169 mono_image_get_generic_param_info (
3170 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3174 mono_image_add_decl_security (assembly,
3175 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3178 MonoDynamicTable *ntable;
3180 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3181 ntable->rows += mono_array_length (tb->subtypes);
3182 alloc_table (ntable, ntable->rows);
3183 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3185 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3186 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3188 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3189 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3190 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3191 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3192 mono_string_to_utf8 (tb->name), tb->table_idx,
3193 ntable->next_idx, ntable->rows);*/
3194 values += MONO_NESTED_CLASS_SIZE;
3201 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3205 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3207 if (!type->subtypes)
3210 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3211 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3212 collect_types (types, subtype);
3217 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3219 if ((*type1)->table_idx < (*type2)->table_idx)
3222 if ((*type1)->table_idx > (*type2)->table_idx)
3229 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3234 for (i = 0; i < mono_array_length (pinfo); ++i) {
3235 MonoReflectionParamBuilder *pb;
3236 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3239 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3244 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3247 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3249 for (i = 0; i < tb->num_fields; ++i) {
3250 MonoReflectionFieldBuilder* fb;
3251 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3252 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3256 for (i = 0; i < mono_array_length (tb->events); ++i) {
3257 MonoReflectionEventBuilder* eb;
3258 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3259 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3262 if (tb->properties) {
3263 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3264 MonoReflectionPropertyBuilder* pb;
3265 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3266 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3270 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3271 MonoReflectionCtorBuilder* cb;
3272 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3273 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3274 params_add_cattrs (assembly, cb->pinfo);
3279 for (i = 0; i < tb->num_methods; ++i) {
3280 MonoReflectionMethodBuilder* mb;
3281 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3282 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3283 params_add_cattrs (assembly, mb->pinfo);
3288 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3289 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3294 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3298 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3300 if (moduleb->global_methods) {
3301 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3302 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3303 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3304 params_add_cattrs (assembly, mb->pinfo);
3308 if (moduleb->global_fields) {
3309 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3310 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3311 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3315 if (moduleb->types) {
3316 for (i = 0; i < moduleb->num_types; ++i)
3317 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3322 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3324 MonoDynamicTable *table;
3328 char *b = blob_size;
3331 table = &assembly->tables [MONO_TABLE_FILE];
3333 alloc_table (table, table->rows);
3334 values = table->values + table->next_idx * MONO_FILE_SIZE;
3335 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3336 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3337 if (module->image->dynamic) {
3338 /* This depends on the fact that the main module is emitted last */
3339 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3340 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3343 path = g_strdup (module->image->name);
3345 mono_sha1_get_digest_from_file (path, hash);
3348 mono_metadata_encode_value (20, b, &b);
3349 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3350 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3355 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3357 MonoDynamicTable *table;
3360 table = &assembly->tables [MONO_TABLE_MODULE];
3361 mb->table_idx = table->next_idx ++;
3362 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3363 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3366 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3367 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3368 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3369 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3373 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3374 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3376 MonoDynamicTable *table;
3380 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3381 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3384 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3386 alloc_table (table, table->rows);
3387 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3389 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3390 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3391 if (klass->nested_in)
3392 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3394 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3395 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3396 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3398 res = table->next_idx;
3402 /* Emit nested types */
3403 if (klass->nested_classes) {
3406 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3407 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3414 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3415 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3420 klass = mono_class_from_mono_type (tb->type.type);
3422 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3424 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3425 parent_index, assembly);
3429 * We need to do this ourselves since klass->nested_classes is not set up.
3432 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3433 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3438 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3439 guint32 module_index, MonoDynamicImage *assembly)
3441 MonoImage *image = module->image;
3445 t = &image->tables [MONO_TABLE_TYPEDEF];
3447 for (i = 0; i < t->rows; ++i) {
3448 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3450 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3451 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3456 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3458 MonoDynamicTable *table;
3464 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3466 if (assemblyb->type_forwarders) {
3467 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3468 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3474 klass = mono_class_from_mono_type (t->type);
3476 scope = resolution_scope_from_image (assembly, klass->image);
3477 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3478 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3481 alloc_table (table, table->rows);
3482 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3484 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3485 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3486 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3487 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3488 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3495 #define align_pointer(base,p)\
3497 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3499 (p) += 4 - (__diff & 3);\
3503 compare_constants (const void *a, const void *b)
3505 const guint32 *a_values = a;
3506 const guint32 *b_values = b;
3507 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3511 compare_semantics (const void *a, const void *b)
3513 const guint32 *a_values = a;
3514 const guint32 *b_values = b;
3515 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3518 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3522 compare_custom_attrs (const void *a, const void *b)
3524 const guint32 *a_values = a;
3525 const guint32 *b_values = b;
3527 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3531 compare_field_marshal (const void *a, const void *b)
3533 const guint32 *a_values = a;
3534 const guint32 *b_values = b;
3536 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3540 compare_nested (const void *a, const void *b)
3542 const guint32 *a_values = a;
3543 const guint32 *b_values = b;
3545 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3549 compare_genericparam (const void *a, const void *b)
3551 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3552 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3554 if ((*b_entry)->owner == (*a_entry)->owner)
3556 (*a_entry)->gparam->type.type->data.generic_param->num -
3557 (*b_entry)->gparam->type.type->data.generic_param->num;
3559 return (*a_entry)->owner - (*b_entry)->owner;
3563 compare_declsecurity_attrs (const void *a, const void *b)
3565 const guint32 *a_values = a;
3566 const guint32 *b_values = b;
3568 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3572 pad_heap (MonoDynamicStream *sh)
3574 if (sh->index & 3) {
3575 int sz = 4 - (sh->index & 3);
3576 memset (sh->data + sh->index, 0, sz);
3583 MonoDynamicStream *stream;
3587 * build_compressed_metadata() fills in the blob of data that represents the
3588 * raw metadata as it will be saved in the PE file. The five streams are output
3589 * and the metadata tables are comnpressed from the guint32 array representation,
3590 * to the compressed on-disk format.
3593 build_compressed_metadata (MonoDynamicImage *assembly)
3595 MonoDynamicTable *table;
3597 guint64 valid_mask = 0;
3598 guint64 sorted_mask;
3599 guint32 heapt_size = 0;
3600 guint32 meta_size = 256; /* allow for header and other stuff */
3601 guint32 table_offset;
3602 guint32 ntables = 0;
3608 struct StreamDesc stream_desc [5];
3610 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3611 for (i = 0; i < assembly->gen_params->len; i++){
3612 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3613 write_generic_param_entry (assembly, entry);
3616 stream_desc [0].name = "#~";
3617 stream_desc [0].stream = &assembly->tstream;
3618 stream_desc [1].name = "#Strings";
3619 stream_desc [1].stream = &assembly->sheap;
3620 stream_desc [2].name = "#US";
3621 stream_desc [2].stream = &assembly->us;
3622 stream_desc [3].name = "#Blob";
3623 stream_desc [3].stream = &assembly->blob;
3624 stream_desc [4].name = "#GUID";
3625 stream_desc [4].stream = &assembly->guid;
3627 /* tables that are sorted */
3628 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3629 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3630 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3631 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3632 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3633 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3635 /* Compute table sizes */
3636 /* the MonoImage has already been created in mono_image_basic_init() */
3637 meta = &assembly->image;
3639 /* sizes should be multiple of 4 */
3640 pad_heap (&assembly->blob);
3641 pad_heap (&assembly->guid);
3642 pad_heap (&assembly->sheap);
3643 pad_heap (&assembly->us);
3645 /* Setup the info used by compute_sizes () */
3646 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3647 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3648 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3650 meta_size += assembly->blob.index;
3651 meta_size += assembly->guid.index;
3652 meta_size += assembly->sheap.index;
3653 meta_size += assembly->us.index;
3655 for (i=0; i < MONO_TABLE_NUM; ++i)
3656 meta->tables [i].rows = assembly->tables [i].rows;
3658 for (i = 0; i < MONO_TABLE_NUM; i++){
3659 if (meta->tables [i].rows == 0)
3661 valid_mask |= (guint64)1 << i;
3663 meta->tables [i].row_size = mono_metadata_compute_size (
3664 meta, i, &meta->tables [i].size_bitfield);
3665 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3667 heapt_size += 24; /* #~ header size */
3668 heapt_size += ntables * 4;
3669 /* make multiple of 4 */
3672 meta_size += heapt_size;
3673 meta->raw_metadata = g_malloc0 (meta_size);
3674 p = (unsigned char*)meta->raw_metadata;
3675 /* the metadata signature */
3676 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3677 /* version numbers and 4 bytes reserved */
3678 int16val = (guint16*)p;
3679 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3680 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3682 /* version string */
3683 int32val = (guint32*)p;
3684 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3686 memcpy (p, meta->version, strlen (meta->version));
3687 p += GUINT32_FROM_LE (*int32val);
3688 align_pointer (meta->raw_metadata, p);
3689 int16val = (guint16*)p;
3690 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3691 *int16val = GUINT16_TO_LE (5); /* number of streams */
3695 * write the stream info.
3697 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3698 table_offset += 3; table_offset &= ~3;
3700 assembly->tstream.index = heapt_size;
3701 for (i = 0; i < 5; ++i) {
3702 int32val = (guint32*)p;
3703 stream_desc [i].stream->offset = table_offset;
3704 *int32val++ = GUINT32_TO_LE (table_offset);
3705 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3706 table_offset += GUINT32_FROM_LE (*int32val);
3707 table_offset += 3; table_offset &= ~3;
3709 strcpy ((char*)p, stream_desc [i].name);
3710 p += strlen (stream_desc [i].name) + 1;
3711 align_pointer (meta->raw_metadata, p);
3714 * now copy the data, the table stream header and contents goes first.
3716 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3717 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3718 int32val = (guint32*)p;
3719 *int32val = GUINT32_TO_LE (0); /* reserved */
3722 if (mono_get_runtime_info ()->framework_version [0] > '1') {
3723 *p++ = 2; /* version */
3726 *p++ = 1; /* version */
3730 if (meta->idx_string_wide)
3732 if (meta->idx_guid_wide)
3734 if (meta->idx_blob_wide)
3737 *p++ = 1; /* reserved */
3738 int64val = (guint64*)p;
3739 *int64val++ = GUINT64_TO_LE (valid_mask);
3740 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3742 int32val = (guint32*)p;
3743 for (i = 0; i < MONO_TABLE_NUM; i++){
3744 if (meta->tables [i].rows == 0)
3746 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3748 p = (unsigned char*)int32val;
3750 /* sort the tables that still need sorting */
3751 table = &assembly->tables [MONO_TABLE_CONSTANT];
3753 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3754 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3756 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3757 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3759 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3760 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3762 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3763 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3765 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3766 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3767 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3769 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3771 /* compress the tables */
3772 for (i = 0; i < MONO_TABLE_NUM; i++){
3775 guint32 bitfield = meta->tables [i].size_bitfield;
3776 if (!meta->tables [i].rows)
3778 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3779 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3780 meta->tables [i].base = (char*)p;
3781 for (row = 1; row <= meta->tables [i].rows; ++row) {
3782 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3783 for (col = 0; col < assembly->tables [i].columns; ++col) {
3784 switch (mono_metadata_table_size (bitfield, col)) {
3786 *p++ = values [col];
3789 *p++ = values [col] & 0xff;
3790 *p++ = (values [col] >> 8) & 0xff;
3793 *p++ = values [col] & 0xff;
3794 *p++ = (values [col] >> 8) & 0xff;
3795 *p++ = (values [col] >> 16) & 0xff;
3796 *p++ = (values [col] >> 24) & 0xff;
3799 g_assert_not_reached ();
3803 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3806 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3807 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3808 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3809 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3810 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3812 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3816 * Some tables in metadata need to be sorted according to some criteria, but
3817 * when methods and fields are first created with reflection, they may be assigned a token
3818 * that doesn't correspond to the final token they will get assigned after the sorting.
3819 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3820 * with the reflection objects that represent them. Once all the tables are set up, the
3821 * reflection objects will contains the correct table index. fixup_method() will fixup the
3822 * tokens for the method with ILGenerator @ilgen.
3825 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3827 guint32 code_idx = GPOINTER_TO_UINT (value);
3828 MonoReflectionILTokenInfo *iltoken;
3829 MonoReflectionFieldBuilder *field;
3830 MonoReflectionCtorBuilder *ctor;
3831 MonoReflectionMethodBuilder *method;
3832 MonoReflectionTypeBuilder *tb;
3833 MonoReflectionArrayMethod *am;
3835 unsigned char *target;
3837 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3838 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3839 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3840 switch (target [3]) {
3841 case MONO_TABLE_FIELD:
3842 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3843 field = (MonoReflectionFieldBuilder *)iltoken->member;
3844 idx = field->table_idx;
3845 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3846 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3847 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3849 g_assert_not_reached ();
3852 case MONO_TABLE_METHOD:
3853 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3854 method = (MonoReflectionMethodBuilder *)iltoken->member;
3855 idx = method->table_idx;
3856 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3857 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3858 idx = ctor->table_idx;
3859 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3860 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3861 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3862 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3864 g_assert_not_reached ();
3867 case MONO_TABLE_TYPEDEF:
3868 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3869 g_assert_not_reached ();
3870 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3871 idx = tb->table_idx;
3873 case MONO_TABLE_MEMBERREF:
3874 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3875 am = (MonoReflectionArrayMethod*)iltoken->member;
3876 idx = am->table_idx;
3877 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3878 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3879 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3880 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3881 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3882 g_assert (m->klass->generic_class || m->klass->generic_container);
3884 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3886 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3887 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3888 g_assert (f->generic_info);
3890 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3891 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3893 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3895 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
3897 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
3900 g_assert_not_reached ();
3903 case MONO_TABLE_METHODSPEC:
3904 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3905 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3906 g_assert (mono_method_signature (m)->generic_param_count);
3908 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3911 g_assert_not_reached ();
3915 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3917 target [0] = idx & 0xff;
3918 target [1] = (idx >> 8) & 0xff;
3919 target [2] = (idx >> 16) & 0xff;
3926 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3927 * value is not known when the table is emitted.
3930 fixup_cattrs (MonoDynamicImage *assembly)
3932 MonoDynamicTable *table;
3934 guint32 type, i, idx, token;
3937 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3939 for (i = 0; i < table->rows; ++i) {
3940 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3942 type = values [MONO_CUSTOM_ATTR_TYPE];
3943 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3944 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3945 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3946 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3949 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3950 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3951 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3952 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3959 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3961 MonoDynamicTable *table;
3964 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3966 alloc_table (table, table->rows);
3967 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3968 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3969 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3970 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3971 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3976 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3978 MonoDynamicTable *table;
3982 char *b = blob_size;
3984 guint32 idx, offset;
3986 if (rsrc->filename) {
3987 name = mono_string_to_utf8 (rsrc->filename);
3988 sname = g_path_get_basename (name);
3990 table = &assembly->tables [MONO_TABLE_FILE];
3992 alloc_table (table, table->rows);
3993 values = table->values + table->next_idx * MONO_FILE_SIZE;
3994 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3995 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3998 mono_sha1_get_digest_from_file (name, hash);
3999 mono_metadata_encode_value (20, b, &b);
4000 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4001 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4003 idx = table->next_idx++;
4005 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4011 data = mono_array_addr (rsrc->data, char, 0);
4012 len = mono_array_length (rsrc->data);
4018 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4019 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4020 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4021 mono_image_add_stream_data (&assembly->resources, data, len);
4025 * The entry should be emitted into the MANIFESTRESOURCE table of
4026 * the main module, but that needs to reference the FILE table
4027 * which isn't emitted yet.
4034 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4038 set_version_from_string (MonoString *version, guint32 *values)
4040 gchar *ver, *p, *str;
4043 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4044 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4045 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4046 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4049 ver = str = mono_string_to_utf8 (version);
4050 for (i = 0; i < 4; ++i) {
4051 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4057 /* handle Revision and Build */
4067 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4071 char *b = blob_size;
4076 len = mono_array_length (pkey);
4077 mono_metadata_encode_value (len, b, &b);
4078 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4079 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4081 assembly->public_key = g_malloc (len);
4082 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4083 assembly->public_key_len = len;
4085 /* Special case: check for ECMA key (16 bytes) */
4086 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4087 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4088 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4089 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4090 /* minimum key size (in 2.0) is 384 bits */
4091 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4093 /* FIXME - verifier */
4094 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4095 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4097 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4103 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4105 MonoDynamicTable *table;
4106 MonoDynamicImage *assembly;
4107 MonoReflectionAssemblyBuilder *assemblyb;
4111 guint32 module_index;
4113 assemblyb = moduleb->assemblyb;
4114 assembly = moduleb->dynamic_image;
4115 domain = mono_object_domain (assemblyb);
4117 /* Emit ASSEMBLY table */
4118 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4119 alloc_table (table, 1);
4120 values = table->values + MONO_ASSEMBLY_SIZE;
4121 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4122 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4123 if (assemblyb->culture) {
4124 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4126 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4128 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4129 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4130 set_version_from_string (assemblyb->version, values);
4132 /* Emit FILE + EXPORTED_TYPE table */
4134 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4136 MonoReflectionModuleBuilder *file_module =
4137 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4138 if (file_module != moduleb) {
4139 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4141 if (file_module->types) {
4142 for (j = 0; j < file_module->num_types; ++j) {
4143 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4144 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4149 if (assemblyb->loaded_modules) {
4150 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4151 MonoReflectionModule *file_module =
4152 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4153 mono_image_fill_file_table (domain, file_module, assembly);
4155 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4158 if (assemblyb->type_forwarders)
4159 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4161 /* Emit MANIFESTRESOURCE table */
4163 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4165 MonoReflectionModuleBuilder *file_module =
4166 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4167 /* The table for the main module is emitted later */
4168 if (file_module != moduleb) {
4170 if (file_module->resources) {
4171 int len = mono_array_length (file_module->resources);
4172 for (j = 0; j < len; ++j) {
4173 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4174 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4182 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4183 * for the modulebuilder @moduleb.
4184 * At the end of the process, method and field tokens are fixed up and the
4185 * on-disk compressed metadata representation is created.
4188 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4190 MonoDynamicTable *table;
4191 MonoDynamicImage *assembly;
4192 MonoReflectionAssemblyBuilder *assemblyb;
4198 assemblyb = moduleb->assemblyb;
4199 assembly = moduleb->dynamic_image;
4200 domain = mono_object_domain (assemblyb);
4202 if (assembly->text_rva)
4205 assembly->text_rva = START_TEXT_RVA;
4207 if (moduleb->is_main) {
4208 mono_image_emit_manifest (moduleb);
4211 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4212 table->rows = 1; /* .<Module> */
4214 alloc_table (table, table->rows);
4216 * Set the first entry.
4218 values = table->values + table->columns;
4219 values [MONO_TYPEDEF_FLAGS] = 0;
4220 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4221 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4222 values [MONO_TYPEDEF_EXTENDS] = 0;
4223 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4224 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4227 * handle global methods
4228 * FIXME: test what to do when global methods are defined in multiple modules.
4230 if (moduleb->global_methods) {
4231 table = &assembly->tables [MONO_TABLE_METHOD];
4232 table->rows += mono_array_length (moduleb->global_methods);
4233 alloc_table (table, table->rows);
4234 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4235 mono_image_get_method_info (
4236 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4238 if (moduleb->global_fields) {
4239 table = &assembly->tables [MONO_TABLE_FIELD];
4240 table->rows += mono_array_length (moduleb->global_fields);
4241 alloc_table (table, table->rows);
4242 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4243 mono_image_get_field_info (
4244 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4247 table = &assembly->tables [MONO_TABLE_MODULE];
4248 alloc_table (table, 1);
4249 mono_image_fill_module_table (domain, moduleb, assembly);
4251 /* Collect all types into a list sorted by their table_idx */
4252 types = g_ptr_array_new ();
4255 for (i = 0; i < moduleb->num_types; ++i) {
4256 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4257 collect_types (types, type);
4260 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4261 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4262 table->rows += types->len;
4263 alloc_table (table, table->rows);
4266 * Emit type names + namespaces at one place inside the string heap,
4267 * so load_class_names () needs to touch fewer pages.
4269 for (i = 0; i < types->len; ++i) {
4270 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4271 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4273 for (i = 0; i < types->len; ++i) {
4274 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4275 string_heap_insert_mstring (&assembly->sheap, tb->name);
4278 for (i = 0; i < types->len; ++i) {
4279 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4280 mono_image_get_type_info (domain, type, assembly);
4284 * table->rows is already set above and in mono_image_fill_module_table.
4286 /* add all the custom attributes at the end, once all the indexes are stable */
4287 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4289 /* CAS assembly permissions */
4290 if (assemblyb->permissions_minimum)
4291 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4292 if (assemblyb->permissions_optional)
4293 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4294 if (assemblyb->permissions_refused)
4295 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4297 module_add_cattrs (assembly, moduleb);
4300 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4302 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4303 * the final tokens and don't need another fixup pass. */
4305 if (moduleb->global_methods) {
4306 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4307 MonoReflectionMethodBuilder *mb = mono_array_get (
4308 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4309 mono_image_add_methodimpl (assembly, mb);
4313 for (i = 0; i < types->len; ++i) {
4314 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4315 if (type->methods) {
4316 for (j = 0; j < type->num_methods; ++j) {
4317 MonoReflectionMethodBuilder *mb = mono_array_get (
4318 type->methods, MonoReflectionMethodBuilder*, j);
4320 mono_image_add_methodimpl (assembly, mb);
4325 g_ptr_array_free (types, TRUE);
4327 fixup_cattrs (assembly);
4331 * mono_image_insert_string:
4332 * @module: module builder object
4335 * Insert @str into the user string stream of @module.
4338 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4340 MonoDynamicImage *assembly;
4345 MONO_ARCH_SAVE_REGS;
4347 if (!module->dynamic_image)
4348 mono_image_module_basic_init (module);
4350 assembly = module->dynamic_image;
4352 if (assembly->save) {
4353 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4354 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4355 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4357 char *swapped = g_malloc (2 * mono_string_length (str));
4358 const char *p = (const char*)mono_string_chars (str);
4360 swap_with_size (swapped, p, 2, mono_string_length (str));
4361 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4365 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4367 mono_image_add_stream_data (&assembly->us, "", 1);
4369 idx = assembly->us.index ++;
4372 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4374 return MONO_TOKEN_STRING | idx;
4378 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4383 klass = obj->vtable->klass;
4384 if (strcmp (klass->name, "MonoMethod") == 0) {
4385 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4386 MonoMethodSignature *sig, *old;
4387 guint32 sig_token, parent;
4390 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4392 nargs = mono_array_length (opt_param_types);
4393 old = mono_method_signature (method);
4394 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4396 sig->hasthis = old->hasthis;
4397 sig->explicit_this = old->explicit_this;
4398 sig->call_convention = old->call_convention;
4399 sig->generic_param_count = old->generic_param_count;
4400 sig->param_count = old->param_count + nargs;
4401 sig->sentinelpos = old->param_count;
4402 sig->ret = old->ret;
4404 for (i = 0; i < old->param_count; i++)
4405 sig->params [i] = old->params [i];
4407 for (i = 0; i < nargs; i++) {
4408 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4409 sig->params [old->param_count + i] = rt->type;
4412 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4413 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4414 parent >>= MONO_TYPEDEFORREF_BITS;
4416 parent <<= MONO_MEMBERREF_PARENT_BITS;
4417 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4419 sig_token = method_encode_signature (assembly, sig);
4420 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4421 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4422 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4423 ReflectionMethodBuilder rmb;
4424 guint32 parent, sig;
4427 reflection_methodbuilder_from_method_builder (&rmb, mb);
4428 rmb.opt_types = opt_param_types;
4430 sig = method_builder_encode_signature (assembly, &rmb);
4432 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4433 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4435 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4436 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4438 name = mono_string_to_utf8 (rmb.name);
4439 token = mono_image_get_varargs_method_token (
4440 assembly, parent, name, sig);
4443 g_error ("requested method token for %s\n", klass->name);
4450 * mono_image_create_token:
4451 * @assembly: a dynamic assembly
4453 * @register_token: Whenever to register the token in the assembly->tokens hash.
4455 * Get a token to insert in the IL code stream for the given MemberInfo.
4456 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4457 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4461 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4462 gboolean create_methodspec, gboolean register_token)
4467 klass = obj->vtable->klass;
4468 if (strcmp (klass->name, "MethodBuilder") == 0) {
4469 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4470 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4472 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4473 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4475 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4476 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4477 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4478 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4479 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4481 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4482 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4484 token = mono_image_get_ctorbuilder_token (assembly, mb);
4485 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4486 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4487 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4488 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4489 if (tb->generic_params) {
4490 token = mono_image_get_generic_field_token (assembly, fb);
4492 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4494 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4495 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4496 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4497 } else if (strcmp (klass->name, "MonoType") == 0) {
4498 MonoReflectionType *tb = (MonoReflectionType *)obj;
4499 MonoClass *mc = mono_class_from_mono_type (tb->type);
4500 token = mono_metadata_token_from_dor (
4501 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4502 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4503 MonoReflectionType *tb = (MonoReflectionType *)obj;
4504 token = mono_metadata_token_from_dor (
4505 mono_image_typedef_or_ref (assembly, tb->type));
4506 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4507 MonoReflectionType *tb = (MonoReflectionType *)obj;
4508 token = mono_metadata_token_from_dor (
4509 mono_image_typedef_or_ref (assembly, tb->type));
4510 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4511 strcmp (klass->name, "MonoMethod") == 0 ||
4512 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4513 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4514 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4515 if (m->method->is_inflated) {
4516 if (create_methodspec)
4517 token = mono_image_get_methodspec_token (assembly, m->method);
4519 token = mono_image_get_inflated_method_token (assembly, m->method);
4520 } else if ((m->method->klass->image == &assembly->image) &&
4521 !m->method->klass->generic_class) {
4522 static guint32 method_table_idx = 0xffffff;
4523 if (m->method->klass->wastypebuilder) {
4524 /* we use the same token as the one that was assigned
4525 * to the Methodbuilder.
4526 * FIXME: do the equivalent for Fields.
4528 token = m->method->token;
4531 * Each token should have a unique index, but the indexes are
4532 * assigned by managed code, so we don't know about them. An
4533 * easy solution is to count backwards...
4535 method_table_idx --;
4536 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4539 token = mono_image_get_methodref_token (assembly, m->method);
4541 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4542 } else if (strcmp (klass->name, "MonoField") == 0) {
4543 MonoReflectionField *f = (MonoReflectionField *)obj;
4544 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4545 static guint32 field_table_idx = 0xffffff;
4547 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4549 token = mono_image_get_fieldref_token (assembly, f);
4551 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4552 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4553 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4554 token = mono_image_get_array_token (assembly, m);
4555 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4556 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4557 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4558 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4559 MonoReflectionType *tb = (MonoReflectionType *)obj;
4560 token = mono_metadata_token_from_dor (
4561 mono_image_typedef_or_ref (assembly, tb->type));
4562 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4563 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4564 token = mono_image_get_field_on_inst_token (assembly, f);
4565 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4566 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4567 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4568 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4569 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4570 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4572 g_error ("requested token for %s\n", klass->name);
4576 mono_image_register_token (assembly, token, obj);
4582 * mono_image_register_token:
4584 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4585 * the Module.ResolveXXXToken () methods to work.
4588 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4590 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4592 /* There could be multiple MethodInfo objects with the same token */
4593 //g_assert (prev == obj);
4595 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4600 guint32 import_lookup_table;
4604 guint32 import_address_table_rva;
4612 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4614 static MonoDynamicImage*
4615 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4617 static const guchar entrycode [16] = {0xff, 0x25, 0};
4618 MonoDynamicImage *image;
4621 const char *version;
4623 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4624 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4626 version = mono_get_runtime_info ()->runtime_version;
4629 image = GC_MALLOC (sizeof (MonoDynamicImage));
4631 image = g_new0 (MonoDynamicImage, 1);
4634 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4636 /*g_print ("created image %p\n", image);*/
4637 /* keep in sync with image.c */
4638 image->image.name = assembly_name;
4639 image->image.assembly_name = image->image.name; /* they may be different */
4640 image->image.module_name = module_name;
4641 image->image.version = g_strdup (version);
4642 image->image.md_version_major = 1;
4643 image->image.md_version_minor = 1;
4644 image->image.dynamic = TRUE;
4646 image->image.references = g_new0 (MonoAssembly*, 1);
4647 image->image.references [0] = NULL;
4649 mono_image_init (&image->image);
4651 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4652 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4653 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4654 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4655 image->handleref = g_hash_table_new (NULL, NULL);
4656 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4657 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4658 image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4659 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4660 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4661 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4662 image->gen_params = g_ptr_array_new ();
4664 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4665 string_heap_init (&image->sheap);
4666 mono_image_add_stream_data (&image->us, "", 1);
4667 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4668 /* import tables... */
4669 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4670 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4671 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4672 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4673 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4674 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4675 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4676 stream_data_align (&image->code);
4678 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4680 for (i=0; i < MONO_TABLE_NUM; ++i) {
4681 image->tables [i].next_idx = 1;
4682 image->tables [i].columns = table_sizes [i];
4685 image->image.assembly = (MonoAssembly*)assembly;
4686 image->run = assembly->run;
4687 image->save = assembly->save;
4688 image->pe_kind = 0x1; /* ILOnly */
4689 image->machine = 0x14c; /* I386 */
4691 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4697 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4703 mono_dynamic_image_free (MonoDynamicImage *image)
4705 MonoDynamicImage *di = image;
4710 mono_g_hash_table_destroy (di->methodspec);
4712 g_hash_table_destroy (di->typespec);
4714 g_hash_table_destroy (di->typeref);
4716 g_hash_table_destroy (di->handleref);
4718 mono_g_hash_table_destroy (di->tokens);
4719 if (di->generic_def_objects)
4720 mono_g_hash_table_destroy (di->generic_def_objects);
4721 if (di->blob_cache) {
4722 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4723 g_hash_table_destroy (di->blob_cache);
4725 for (list = di->array_methods; list; list = list->next) {
4726 ArrayMethod *am = (ArrayMethod *)list->data;
4731 g_list_free (di->array_methods);
4732 if (di->gen_params) {
4733 for (i = 0; i < di->gen_params->len; i++) {
4734 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4735 if (entry->gparam->type.type) {
4736 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4737 g_free ((char*)param->name);
4739 g_free (entry->gparam->type.type);
4743 g_ptr_array_free (di->gen_params, TRUE);
4745 if (di->token_fixups)
4746 mono_g_hash_table_destroy (di->token_fixups);
4747 if (di->method_to_table_idx)
4748 g_hash_table_destroy (di->method_to_table_idx);
4749 if (di->field_to_table_idx)
4750 g_hash_table_destroy (di->field_to_table_idx);
4751 if (di->method_aux_hash)
4752 g_hash_table_destroy (di->method_aux_hash);
4753 g_free (di->strong_name);
4754 g_free (di->win32_res);
4756 g_free (di->public_key);
4758 /*g_print ("string heap destroy for image %p\n", di);*/
4759 mono_dynamic_stream_reset (&di->sheap);
4760 mono_dynamic_stream_reset (&di->code);
4761 mono_dynamic_stream_reset (&di->resources);
4762 mono_dynamic_stream_reset (&di->us);
4763 mono_dynamic_stream_reset (&di->blob);
4764 mono_dynamic_stream_reset (&di->tstream);
4765 mono_dynamic_stream_reset (&di->guid);
4766 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4767 g_free (di->tables [i].values);
4772 * mono_image_basic_init:
4773 * @assembly: an assembly builder object
4775 * Create the MonoImage that represents the assembly builder and setup some
4776 * of the helper hash table and the basic metadata streams.
4779 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4781 MonoDynamicAssembly *assembly;
4782 MonoDynamicImage *image;
4783 MonoDomain *domain = mono_object_domain (assemblyb);
4785 MONO_ARCH_SAVE_REGS;
4787 if (assemblyb->dynamic_assembly)
4791 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4793 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4796 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4798 assembly->assembly.ref_count = 1;
4799 assembly->assembly.dynamic = TRUE;
4800 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4801 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4802 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4803 if (assemblyb->culture)
4804 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4806 assembly->assembly.aname.culture = g_strdup ("");
4808 if (assemblyb->version) {
4809 char *vstr = mono_string_to_utf8 (assemblyb->version);
4810 char **version = g_strsplit (vstr, ".", 4);
4811 char **parts = version;
4812 assembly->assembly.aname.major = atoi (*parts++);
4813 assembly->assembly.aname.minor = atoi (*parts++);
4814 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4815 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4817 g_strfreev (version);
4820 assembly->assembly.aname.major = 0;
4821 assembly->assembly.aname.minor = 0;
4822 assembly->assembly.aname.build = 0;
4823 assembly->assembly.aname.revision = 0;
4826 assembly->run = assemblyb->access != 2;
4827 assembly->save = assemblyb->access != 1;
4829 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4830 image->initial_image = TRUE;
4831 assembly->assembly.aname.name = image->image.name;
4832 assembly->assembly.image = &image->image;
4834 mono_domain_assemblies_lock (domain);
4835 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4836 mono_domain_assemblies_unlock (domain);
4838 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4840 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4842 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4846 calc_section_size (MonoDynamicImage *assembly)
4850 /* alignment constraints */
4851 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4852 g_assert ((assembly->code.index % 4) == 0);
4853 assembly->meta_size += 3;
4854 assembly->meta_size &= ~3;
4855 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4856 g_assert ((assembly->resources.index % 4) == 0);
4858 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4859 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4862 if (assembly->win32_res) {
4863 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4865 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4866 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4870 assembly->sections [MONO_SECTION_RELOC].size = 12;
4871 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4881 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4885 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4887 ResTreeNode *t1 = (ResTreeNode*)a;
4888 ResTreeNode *t2 = (ResTreeNode*)b;
4890 return t1->id - t2->id;
4894 * resource_tree_create:
4896 * Organize the resources into a resource tree.
4898 static ResTreeNode *
4899 resource_tree_create (MonoArray *win32_resources)
4901 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4905 tree = g_new0 (ResTreeNode, 1);
4907 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4908 MonoReflectionWin32Resource *win32_res =
4909 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4913 /* FIXME: BUG: this stores managed references in unmanaged memory */
4914 lang_node = g_new0 (ResTreeNode, 1);
4915 lang_node->id = win32_res->lang_id;
4916 lang_node->win32_res = win32_res;
4918 /* Create type node if neccesary */
4920 for (l = tree->children; l; l = l->next)
4921 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4922 type_node = (ResTreeNode*)l->data;
4927 type_node = g_new0 (ResTreeNode, 1);
4928 type_node->id = win32_res->res_type;
4931 * The resource types have to be sorted otherwise
4932 * Windows Explorer can't display the version information.
4934 tree->children = g_slist_insert_sorted (tree->children,
4935 type_node, resource_tree_compare_by_id);
4938 /* Create res node if neccesary */
4940 for (l = type_node->children; l; l = l->next)
4941 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4942 res_node = (ResTreeNode*)l->data;
4947 res_node = g_new0 (ResTreeNode, 1);
4948 res_node->id = win32_res->res_id;
4949 type_node->children = g_slist_append (type_node->children, res_node);
4952 res_node->children = g_slist_append (res_node->children, lang_node);
4959 * resource_tree_encode:
4961 * Encode the resource tree into the format used in the PE file.
4964 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4967 MonoPEResourceDir dir;
4968 MonoPEResourceDirEntry dir_entry;
4969 MonoPEResourceDataEntry data_entry;
4971 guint32 res_id_entries;
4974 * For the format of the resource directory, see the article
4975 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4979 memset (&dir, 0, sizeof (dir));
4980 memset (&dir_entry, 0, sizeof (dir_entry));
4981 memset (&data_entry, 0, sizeof (data_entry));
4983 g_assert (sizeof (dir) == 16);
4984 g_assert (sizeof (dir_entry) == 8);
4985 g_assert (sizeof (data_entry) == 16);
4987 node->offset = p - begin;
4989 /* IMAGE_RESOURCE_DIRECTORY */
4990 res_id_entries = g_slist_length (node->children);
4991 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
4993 memcpy (p, &dir, sizeof (dir));
4996 /* Reserve space for entries */
4998 p += sizeof (dir_entry) * res_id_entries;
5000 /* Write children */
5001 for (l = node->children; l; l = l->next) {
5002 ResTreeNode *child = (ResTreeNode*)l->data;
5004 if (child->win32_res) {
5007 child->offset = p - begin;
5009 /* IMAGE_RESOURCE_DATA_ENTRY */
5010 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5011 size = mono_array_length (child->win32_res->res_data);
5012 data_entry.rde_size = GUINT32_TO_LE (size);
5014 memcpy (p, &data_entry, sizeof (data_entry));
5015 p += sizeof (data_entry);
5017 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5020 resource_tree_encode (child, begin, p, &p);
5024 /* IMAGE_RESOURCE_ENTRY */
5025 for (l = node->children; l; l = l->next) {
5026 ResTreeNode *child = (ResTreeNode*)l->data;
5028 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5029 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5031 memcpy (entries, &dir_entry, sizeof (dir_entry));
5032 entries += sizeof (dir_entry);
5039 resource_tree_free (ResTreeNode * node)
5042 for (list = node->children; list; list = list->next)
5043 resource_tree_free ((ResTreeNode*)list->data);
5044 g_slist_free(node->children);
5049 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5054 MonoReflectionWin32Resource *win32_res;
5057 if (!assemblyb->win32_resources)
5061 * Resources are stored in a three level tree inside the PE file.
5062 * - level one contains a node for each type of resource
5063 * - level two contains a node for each resource
5064 * - level three contains a node for each instance of a resource for a
5065 * specific language.
5068 tree = resource_tree_create (assemblyb->win32_resources);
5070 /* Estimate the size of the encoded tree */
5072 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5073 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5074 size += mono_array_length (win32_res->res_data);
5076 /* Directory structure */
5077 size += mono_array_length (assemblyb->win32_resources) * 256;
5078 p = buf = g_malloc (size);
5080 resource_tree_encode (tree, p, p, &p);
5082 g_assert (p - buf <= size);
5084 assembly->win32_res = g_malloc (p - buf);
5085 assembly->win32_res_size = p - buf;
5086 memcpy (assembly->win32_res, buf, p - buf);
5089 resource_tree_free (tree);
5093 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5095 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5098 p += sizeof (MonoPEResourceDir);
5099 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5100 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5101 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5102 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5103 fixup_resource_directory (res_section, child, rva);
5105 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5106 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5109 p += sizeof (MonoPEResourceDirEntry);
5114 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5117 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5118 g_error ("WriteFile returned %d\n", GetLastError ());
5122 * mono_image_create_pefile:
5123 * @mb: a module builder object
5125 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5126 * assembly->pefile where it can be easily retrieved later in chunks.
5129 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
5130 MonoMSDOSHeader *msdos;
5131 MonoDotNetHeader *header;
5132 MonoSectionTable *section;
5133 MonoCLIHeader *cli_header;
5134 guint32 size, image_size, virtual_base, text_offset;
5135 guint32 header_start, section_start, file_offset, virtual_offset;
5136 MonoDynamicImage *assembly;
5137 MonoReflectionAssemblyBuilder *assemblyb;
5138 MonoDynamicStream pefile_stream = {0};
5139 MonoDynamicStream *pefile = &pefile_stream;
5141 guint32 *rva, value;
5143 static const unsigned char msheader[] = {
5144 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5145 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5148 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5149 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5150 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5151 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5154 assemblyb = mb->assemblyb;
5156 mono_image_basic_init (assemblyb);
5157 assembly = mb->dynamic_image;
5159 assembly->pe_kind = assemblyb->pe_kind;
5160 assembly->machine = assemblyb->machine;
5161 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5162 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5164 mono_image_build_metadata (mb);
5166 if (mb->is_main && assemblyb->resources) {
5167 int len = mono_array_length (assemblyb->resources);
5168 for (i = 0; i < len; ++i)
5169 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5172 if (mb->resources) {
5173 int len = mono_array_length (mb->resources);
5174 for (i = 0; i < len; ++i)
5175 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5178 build_compressed_metadata (assembly);
5181 assembly_add_win32_resources (assembly, assemblyb);
5183 nsections = calc_section_size (assembly);
5185 /* The DOS header and stub */
5186 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5187 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5189 /* the dotnet header */
5190 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5192 /* the section tables */
5193 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5195 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5196 virtual_offset = VIRT_ALIGN;
5199 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5200 if (!assembly->sections [i].size)
5203 file_offset += FILE_ALIGN - 1;
5204 file_offset &= ~(FILE_ALIGN - 1);
5205 virtual_offset += VIRT_ALIGN - 1;
5206 virtual_offset &= ~(VIRT_ALIGN - 1);
5208 assembly->sections [i].offset = file_offset;
5209 assembly->sections [i].rva = virtual_offset;
5211 file_offset += assembly->sections [i].size;
5212 virtual_offset += assembly->sections [i].size;
5213 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5216 file_offset += FILE_ALIGN - 1;
5217 file_offset &= ~(FILE_ALIGN - 1);
5219 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5221 /* back-patch info */
5222 msdos = (MonoMSDOSHeader*)pefile->data;
5223 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5225 header = (MonoDotNetHeader*)(pefile->data + header_start);
5226 header->pesig [0] = 'P';
5227 header->pesig [1] = 'E';
5229 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5230 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5231 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5232 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5233 if (assemblyb->pekind == 1) {
5235 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5238 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5241 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5243 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5244 header->pe.pe_major = 6;
5245 header->pe.pe_minor = 0;
5246 size = assembly->sections [MONO_SECTION_TEXT].size;
5247 size += FILE_ALIGN - 1;
5248 size &= ~(FILE_ALIGN - 1);
5249 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5250 size = assembly->sections [MONO_SECTION_RSRC].size;
5251 size += FILE_ALIGN - 1;
5252 size &= ~(FILE_ALIGN - 1);
5253 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5254 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5255 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5256 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5257 /* pe_rva_entry_point always at the beginning of the text section */
5258 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5260 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5261 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5262 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5263 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5264 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5265 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5266 size = section_start;
5267 size += FILE_ALIGN - 1;
5268 size &= ~(FILE_ALIGN - 1);
5269 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5271 size += VIRT_ALIGN - 1;
5272 size &= ~(VIRT_ALIGN - 1);
5273 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5276 // Translate the PEFileKind value to the value expected by the Windows loader
5282 // PEFileKinds.Dll == 1
5283 // PEFileKinds.ConsoleApplication == 2
5284 // PEFileKinds.WindowApplication == 3
5287 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5288 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5290 if (assemblyb->pekind == 3)
5295 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5297 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5298 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5299 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5300 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5301 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5302 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5304 /* fill data directory entries */
5306 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5307 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5309 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5310 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5312 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5313 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5314 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5315 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5316 /* patch entrypoint name */
5317 if (assemblyb->pekind == 1)
5318 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5320 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5321 /* patch imported function RVA name */
5322 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5323 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5325 /* the import table */
5326 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5327 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5328 /* patch imported dll RVA name and other entries in the dir */
5329 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5330 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5331 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5332 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5333 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5334 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5336 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5337 value = (assembly->text_rva + assembly->imp_names_offset);
5338 *p++ = (value) & 0xff;
5339 *p++ = (value >> 8) & (0xff);
5340 *p++ = (value >> 16) & (0xff);
5341 *p++ = (value >> 24) & (0xff);
5343 /* the CLI header info */
5344 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5345 cli_header->ch_size = GUINT32_FROM_LE (72);
5346 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5347 if (mono_get_runtime_info ()->framework_version [0] > '1')
5348 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5350 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5351 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5352 if (assemblyb->entry_point) {
5353 guint32 table_idx = 0;
5354 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5355 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5356 table_idx = methodb->table_idx;
5358 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5360 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5362 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5364 /* The embedded managed resources */
5365 text_offset = assembly->text_rva + assembly->code.index;
5366 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5367 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5368 text_offset += assembly->resources.index;
5369 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5370 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5371 text_offset += assembly->meta_size;
5372 if (assembly->strong_name_size) {
5373 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5374 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5375 text_offset += assembly->strong_name_size;
5378 /* write the section tables and section content */
5379 section = (MonoSectionTable*)(pefile->data + section_start);
5380 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5381 static const char section_names [][7] = {
5382 ".text", ".rsrc", ".reloc"
5384 if (!assembly->sections [i].size)
5386 strcpy (section->st_name, section_names [i]);
5387 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5388 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5389 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5390 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5391 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5392 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5393 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5397 checked_write_file (file, pefile->data, pefile->index);
5399 mono_dynamic_stream_reset (pefile);
5401 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5402 if (!assembly->sections [i].size)
5405 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5406 g_error ("SetFilePointer returned %d\n", GetLastError ());
5409 case MONO_SECTION_TEXT:
5410 /* patch entry point */
5411 p = (guchar*)(assembly->code.data + 2);
5412 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5413 *p++ = (value) & 0xff;
5414 *p++ = (value >> 8) & 0xff;
5415 *p++ = (value >> 16) & 0xff;
5416 *p++ = (value >> 24) & 0xff;
5418 checked_write_file (file, assembly->code.data, assembly->code.index);
5419 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5420 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5421 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5424 g_free (assembly->image.raw_metadata);
5426 case MONO_SECTION_RELOC: {
5430 guint16 type_and_offset;
5434 g_assert (sizeof (reloc) == 12);
5436 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5437 reloc.block_size = GUINT32_FROM_LE (12);
5440 * the entrypoint is always at the start of the text section
5441 * 3 is IMAGE_REL_BASED_HIGHLOW
5442 * 2 is patch_size_rva - text_rva
5444 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5447 checked_write_file (file, &reloc, sizeof (reloc));
5451 case MONO_SECTION_RSRC:
5452 if (assembly->win32_res) {
5454 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5455 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5456 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5460 g_assert_not_reached ();
5464 /* check that the file is properly padded */
5465 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5466 g_error ("SetFilePointer returned %d\n", GetLastError ());
5467 if (! SetEndOfFile (file))
5468 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5470 mono_dynamic_stream_reset (&assembly->code);
5471 mono_dynamic_stream_reset (&assembly->us);
5472 mono_dynamic_stream_reset (&assembly->blob);
5473 mono_dynamic_stream_reset (&assembly->guid);
5474 mono_dynamic_stream_reset (&assembly->sheap);
5476 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5477 g_hash_table_destroy (assembly->blob_cache);
5478 assembly->blob_cache = NULL;
5481 MonoReflectionModule *
5482 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5486 MonoImageOpenStatus status;
5487 MonoDynamicAssembly *assembly;
5488 guint32 module_count;
5489 MonoImage **new_modules;
5490 gboolean *new_modules_loaded;
5492 name = mono_string_to_utf8 (fileName);
5494 image = mono_image_open (name, &status);
5497 if (status == MONO_IMAGE_ERROR_ERRNO)
5498 exc = mono_get_exception_file_not_found (fileName);
5500 exc = mono_get_exception_bad_image_format (name);
5502 mono_raise_exception (exc);
5507 assembly = ab->dynamic_assembly;
5508 image->assembly = (MonoAssembly*)assembly;
5510 module_count = image->assembly->image->module_count;
5511 new_modules = g_new0 (MonoImage *, module_count + 1);
5512 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5514 if (image->assembly->image->modules)
5515 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5516 if (image->assembly->image->modules_loaded)
5517 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5518 new_modules [module_count] = image;
5519 new_modules_loaded [module_count] = TRUE;
5520 mono_image_addref (image);
5522 g_free (image->assembly->image->modules);
5523 image->assembly->image->modules = new_modules;
5524 image->assembly->image->modules_loaded = new_modules_loaded;
5525 image->assembly->image->module_count ++;
5527 mono_assembly_load_references (image, &status);
5529 mono_image_close (image);
5530 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5533 return mono_module_get_object (mono_domain_get (), image);
5537 * We need to return always the same object for MethodInfo, FieldInfo etc..
5538 * but we need to consider the reflected type.
5539 * type uses a different hash, since it uses custom hash/equal functions.
5544 MonoClass *refclass;
5548 reflected_equal (gconstpointer a, gconstpointer b) {
5549 const ReflectedEntry *ea = a;
5550 const ReflectedEntry *eb = b;
5552 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5556 reflected_hash (gconstpointer a) {
5557 const ReflectedEntry *ea = a;
5558 return mono_aligned_addr_hash (ea->item);
5561 #define CHECK_OBJECT(t,p,k) \
5567 mono_domain_lock (domain); \
5568 if (!domain->refobject_hash) \
5569 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5570 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5571 mono_domain_unlock (domain); \
5574 mono_domain_unlock (domain); \
5577 #ifndef HAVE_NULL_GC
5578 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5580 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5583 #define CACHE_OBJECT(t,p,o,k) \
5586 ReflectedEntry pe; \
5588 pe.refclass = (k); \
5589 mono_domain_lock (domain); \
5590 if (!domain->refobject_hash) \
5591 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5592 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5594 ReflectedEntry *e = ALLOC_REFENTRY; \
5596 e->refclass = (k); \
5597 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5600 mono_domain_unlock (domain); \
5605 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5607 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5611 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5613 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5617 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5619 MonoDynamicImage *image = moduleb->dynamic_image;
5620 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5623 MonoImage **new_modules;
5626 * FIXME: we already created an image in mono_image_basic_init (), but
5627 * we don't know which module it belongs to, since that is only
5628 * determined at assembly save time.
5630 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5631 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5633 moduleb->module.image = &image->image;
5634 moduleb->dynamic_image = image;
5635 register_module (mono_object_domain (moduleb), moduleb, image);
5637 /* register the module with the assembly */
5638 ass = ab->dynamic_assembly->assembly.image;
5639 module_count = ass->module_count;
5640 new_modules = g_new0 (MonoImage *, module_count + 1);
5643 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5644 new_modules [module_count] = &image->image;
5645 mono_image_addref (&image->image);
5647 g_free (ass->modules);
5648 ass->modules = new_modules;
5649 ass->module_count ++;
5654 * mono_assembly_get_object:
5655 * @domain: an app domain
5656 * @assembly: an assembly
5658 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5660 MonoReflectionAssembly*
5661 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5663 static MonoClass *System_Reflection_Assembly;
5664 MonoReflectionAssembly *res;
5666 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5667 if (!System_Reflection_Assembly)
5668 System_Reflection_Assembly = mono_class_from_name (
5669 mono_defaults.corlib, "System.Reflection", "Assembly");
5670 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5671 res->assembly = assembly;
5673 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5678 MonoReflectionModule*
5679 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5681 static MonoClass *System_Reflection_Module;
5682 MonoReflectionModule *res;
5685 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5686 if (!System_Reflection_Module)
5687 System_Reflection_Module = mono_class_from_name (
5688 mono_defaults.corlib, "System.Reflection", "Module");
5689 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5692 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5694 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5695 basename = g_path_get_basename (image->name);
5696 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5697 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5701 if (image->assembly->image == image) {
5702 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5706 if (image->assembly->image->modules) {
5707 for (i = 0; i < image->assembly->image->module_count; i++) {
5708 if (image->assembly->image->modules [i] == image)
5709 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5711 g_assert (res->token);
5715 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5718 MonoReflectionModule*
5719 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5721 static MonoClass *System_Reflection_Module;
5722 MonoReflectionModule *res;
5723 MonoTableInfo *table;
5724 guint32 cols [MONO_FILE_SIZE];
5726 guint32 i, name_idx;
5729 if (!System_Reflection_Module)
5730 System_Reflection_Module = mono_class_from_name (
5731 mono_defaults.corlib, "System.Reflection", "Module");
5732 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5734 table = &image->tables [MONO_TABLE_FILE];
5735 g_assert (table_index < table->rows);
5736 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5739 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5740 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5742 /* Check whenever the row has a corresponding row in the moduleref table */
5743 table = &image->tables [MONO_TABLE_MODULEREF];
5744 for (i = 0; i < table->rows; ++i) {
5745 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5746 val = mono_metadata_string_heap (image, name_idx);
5747 if (strcmp (val, name) == 0)
5748 res->image = image->modules [i];
5751 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5752 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5753 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5754 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5755 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5761 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5763 if ((t1->type != t2->type) ||
5764 (t1->byref != t2->byref))
5768 case MONO_TYPE_VOID:
5769 case MONO_TYPE_BOOLEAN:
5770 case MONO_TYPE_CHAR:
5781 case MONO_TYPE_STRING:
5784 case MONO_TYPE_OBJECT:
5785 case MONO_TYPE_TYPEDBYREF:
5787 case MONO_TYPE_VALUETYPE:
5788 case MONO_TYPE_CLASS:
5789 case MONO_TYPE_SZARRAY:
5790 return t1->data.klass == t2->data.klass;
5792 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5793 case MONO_TYPE_ARRAY:
5794 if (t1->data.array->rank != t2->data.array->rank)
5796 return t1->data.array->eklass == t2->data.array->eklass;
5797 case MONO_TYPE_GENERICINST: {
5799 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5800 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5801 if (i1->type_argc != i2->type_argc)
5803 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5804 &t2->data.generic_class->container_class->byval_arg))
5806 /* FIXME: we should probably just compare the instance pointers directly. */
5807 for (i = 0; i < i1->type_argc; ++i) {
5808 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5814 case MONO_TYPE_MVAR:
5815 return t1->data.generic_param == t2->data.generic_param;
5817 g_error ("implement type compare for %0x!", t1->type);
5825 mymono_metadata_type_hash (MonoType *t1)
5831 hash |= t1->byref << 6; /* do not collide with t1->type values */
5833 case MONO_TYPE_VALUETYPE:
5834 case MONO_TYPE_CLASS:
5835 case MONO_TYPE_SZARRAY:
5836 /* check if the distribution is good enough */
5837 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5839 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5840 case MONO_TYPE_GENERICINST: {
5842 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5843 hash += g_str_hash (t1->data.generic_class->container_class->name);
5845 for (i = 0; i < inst->type_argc; ++i) {
5846 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5855 static MonoReflectionGenericClass*
5856 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5858 static MonoClass *System_Reflection_MonoGenericClass;
5859 MonoReflectionGenericClass *res;
5860 MonoClass *klass, *gklass;
5862 if (!System_Reflection_MonoGenericClass) {
5863 System_Reflection_MonoGenericClass = mono_class_from_name (
5864 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5865 g_assert (System_Reflection_MonoGenericClass);
5868 klass = mono_class_from_mono_type (geninst);
5869 gklass = klass->generic_class->container_class;
5871 mono_class_init (klass);
5874 /* FIXME: allow unpinned later */
5875 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5877 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5880 res->type.type = geninst;
5881 g_assert (gklass->reflection_info);
5882 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
5883 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5889 verify_safe_for_managed_space (MonoType *type)
5891 switch (type->type) {
5893 case MONO_TYPE_ARRAY:
5894 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5896 return verify_safe_for_managed_space (type->data.type);
5897 case MONO_TYPE_SZARRAY:
5898 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5899 case MONO_TYPE_GENERICINST: {
5900 MonoGenericInst *inst = type->data.generic_class->inst;
5904 for (i = 0; i < inst->type_argc; ++i)
5905 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5911 case MONO_TYPE_MVAR:
5918 * mono_type_get_object:
5919 * @domain: an app domain
5922 * Return an System.MonoType object representing the type @type.
5925 mono_type_get_object (MonoDomain *domain, MonoType *type)
5927 MonoReflectionType *res;
5928 MonoClass *klass = mono_class_from_mono_type (type);
5930 /*we must avoid using @type as it might have come
5931 * from a mono_metadata_type_dup and the caller
5932 * expects that is can be freed.
5933 * Using the right type from
5935 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
5938 * If the vtable of the given class was already created, we can use
5939 * the MonoType from there and avoid all locking and hash table lookups.
5941 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
5942 * that the resulting object is diferent.
5944 if (type == &klass->byval_arg && !klass->image->dynamic) {
5945 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
5946 if (vtable && vtable->type)
5947 return vtable->type;
5950 mono_domain_lock (domain);
5951 if (!domain->type_hash)
5952 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5953 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5954 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5955 mono_domain_unlock (domain);
5958 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
5959 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
5960 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5961 mono_g_hash_table_insert (domain->type_hash, type, res);
5962 mono_domain_unlock (domain);
5966 if (!verify_safe_for_managed_space (type)) {
5967 mono_domain_unlock (domain);
5968 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5971 if (klass->reflection_info && !klass->wastypebuilder) {
5972 /* g_assert_not_reached (); */
5973 /* should this be considered an error condition? */
5975 mono_domain_unlock (domain);
5976 return klass->reflection_info;
5979 // FIXME: Get rid of this, do it in the icalls for Type
5980 mono_class_init (klass);
5982 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5984 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5987 mono_g_hash_table_insert (domain->type_hash, type, res);
5988 mono_domain_unlock (domain);
5993 * mono_method_get_object:
5994 * @domain: an app domain
5996 * @refclass: the reflected type (can be NULL)
5998 * Return an System.Reflection.MonoMethod object representing the method @method.
6000 MonoReflectionMethod*
6001 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6004 * We use the same C representation for methods and constructors, but the type
6005 * name in C# is different.
6007 static MonoClass *System_Reflection_MonoMethod = NULL;
6008 static MonoClass *System_Reflection_MonoCMethod = NULL;
6009 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6010 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6012 MonoReflectionMethod *ret;
6015 * Don't let static RGCTX invoke wrappers get into
6016 * MonoReflectionMethods.
6018 if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
6019 method = mono_marshal_method_from_wrapper (method);
6021 if (method->is_inflated) {
6022 MonoReflectionGenericMethod *gret;
6024 refclass = method->klass;
6025 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6026 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6027 if (!System_Reflection_MonoGenericCMethod)
6028 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6029 klass = System_Reflection_MonoGenericCMethod;
6031 if (!System_Reflection_MonoGenericMethod)
6032 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6033 klass = System_Reflection_MonoGenericMethod;
6035 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6036 gret->method.method = method;
6037 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6038 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6039 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6043 refclass = method->klass;
6045 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6046 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6047 if (!System_Reflection_MonoCMethod)
6048 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6049 klass = System_Reflection_MonoCMethod;
6052 if (!System_Reflection_MonoMethod)
6053 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6054 klass = System_Reflection_MonoMethod;
6056 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6057 ret->method = method;
6058 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6059 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6063 * mono_field_get_object:
6064 * @domain: an app domain
6068 * Return an System.Reflection.MonoField object representing the field @field
6071 MonoReflectionField*
6072 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6074 MonoReflectionField *res;
6075 static MonoClass *monofield_klass;
6077 CHECK_OBJECT (MonoReflectionField *, field, klass);
6078 if (!monofield_klass)
6079 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6080 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6083 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
6084 if (field->generic_info)
6085 res->attrs = field->generic_info->generic_type->attrs;
6087 res->attrs = field->type->attrs;
6088 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6089 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6093 * mono_property_get_object:
6094 * @domain: an app domain
6096 * @property: a property
6098 * Return an System.Reflection.MonoProperty object representing the property @property
6101 MonoReflectionProperty*
6102 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6104 MonoReflectionProperty *res;
6105 static MonoClass *monoproperty_klass;
6107 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6108 if (!monoproperty_klass)
6109 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6110 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6112 res->property = property;
6113 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6117 * mono_event_get_object:
6118 * @domain: an app domain
6122 * Return an System.Reflection.MonoEvent object representing the event @event
6125 MonoReflectionEvent*
6126 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6128 MonoReflectionEvent *res;
6129 static MonoClass *monoevent_klass;
6131 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6132 if (!monoevent_klass)
6133 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6134 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6137 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6141 * mono_get_reflection_missing_object:
6142 * @domain: Domain where the object lives
6144 * Returns the System.Reflection.Missing.Value singleton object
6145 * (of type System.Reflection.Missing).
6147 * Used as the value for ParameterInfo.DefaultValue when Optional
6151 mono_get_reflection_missing_object (MonoDomain *domain)
6154 static MonoClassField *missing_value_field = NULL;
6156 if (!missing_value_field) {
6157 MonoClass *missing_klass;
6158 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6159 mono_class_init (missing_klass);
6160 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6161 g_assert (missing_value_field);
6163 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6169 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6172 *dbnull = mono_get_dbnull_object (domain);
6177 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6179 if (!*reflection_missing)
6180 *reflection_missing = mono_get_reflection_missing_object (domain);
6181 return *reflection_missing;
6185 * mono_param_get_objects:
6186 * @domain: an app domain
6189 * Return an System.Reflection.ParameterInfo array object representing the parameters
6190 * in the method @method.
6193 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6195 static MonoClass *System_Reflection_ParameterInfo;
6196 static MonoClass *System_Reflection_ParameterInfo_array;
6197 MonoArray *res = NULL;
6198 MonoReflectionMethod *member = NULL;
6199 MonoReflectionParameter *param = NULL;
6200 char **names, **blobs = NULL;
6201 guint32 *types = NULL;
6202 MonoType *type = NULL;
6203 MonoObject *dbnull = NULL;
6204 MonoObject *missing = NULL;
6205 MonoMarshalSpec **mspecs;
6206 MonoMethodSignature *sig;
6207 MonoVTable *pinfo_vtable;
6210 if (!System_Reflection_ParameterInfo_array) {
6213 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6214 mono_memory_barrier ();
6215 System_Reflection_ParameterInfo = klass;
6217 klass = mono_array_class_get (klass, 1);
6218 mono_memory_barrier ();
6219 System_Reflection_ParameterInfo_array = klass;
6222 if (!mono_method_signature (method)->param_count)
6223 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6225 /* Note: the cache is based on the address of the signature into the method
6226 * since we already cache MethodInfos with the method as keys.
6228 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6230 sig = mono_method_signature (method);
6231 member = mono_method_get_object (domain, method, NULL);
6232 names = g_new (char *, sig->param_count);
6233 mono_method_get_param_names (method, (const char **) names);
6235 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6236 mono_method_get_marshal_info (method, mspecs);
6238 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6239 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6240 for (i = 0; i < sig->param_count; ++i) {
6241 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6242 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6243 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6244 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6245 param->PositionImpl = i;
6246 param->AttrsImpl = sig->params [i]->attrs;
6248 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6249 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6250 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6252 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6256 blobs = g_new0 (char *, sig->param_count);
6257 types = g_new0 (guint32, sig->param_count);
6258 get_default_param_value_blobs (method, blobs, types);
6261 /* Build MonoType for the type from the Constant Table */
6263 type = g_new0 (MonoType, 1);
6264 type->type = types [i];
6265 type->data.klass = NULL;
6266 if (types [i] == MONO_TYPE_CLASS)
6267 type->data.klass = mono_defaults.object_class;
6268 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6269 /* For enums, types [i] contains the base type */
6271 type->type = MONO_TYPE_VALUETYPE;
6272 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6274 type->data.klass = mono_class_from_mono_type (type);
6276 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6278 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6279 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6280 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6281 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6283 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6289 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6291 mono_array_setref (res, i, param);
6298 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6300 mono_metadata_free_marshal_spec (mspecs [i]);
6303 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6307 * mono_method_body_get_object:
6308 * @domain: an app domain
6311 * Return an System.Reflection.MethodBody object representing the method @method.
6313 MonoReflectionMethodBody*
6314 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6316 static MonoClass *System_Reflection_MethodBody = NULL;
6317 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6318 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6319 MonoReflectionMethodBody *ret;
6320 MonoMethodNormal *mn;
6321 MonoMethodHeader *header;
6322 guint32 method_rva, local_var_sig_token;
6324 unsigned char format, flags;
6327 if (!System_Reflection_MethodBody)
6328 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6329 if (!System_Reflection_LocalVariableInfo)
6330 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6331 if (!System_Reflection_ExceptionHandlingClause)
6332 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6334 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6336 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6337 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6338 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6339 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6341 mn = (MonoMethodNormal *)method;
6342 header = mono_method_get_header (method);
6344 /* Obtain local vars signature token */
6345 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6346 ptr = mono_image_rva_map (method->klass->image, method_rva);
6347 flags = *(const unsigned char *) ptr;
6348 format = flags & METHOD_HEADER_FORMAT_MASK;
6350 case METHOD_HEADER_TINY_FORMAT:
6351 case METHOD_HEADER_TINY_FORMAT1:
6352 local_var_sig_token = 0;
6354 case METHOD_HEADER_FAT_FORMAT:
6358 local_var_sig_token = read32 (ptr);
6361 g_assert_not_reached ();
6364 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6366 ret->init_locals = header->init_locals;
6367 ret->max_stack = header->max_stack;
6368 ret->local_var_sig_token = local_var_sig_token;
6369 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6370 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6373 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6374 for (i = 0; i < header->num_locals; ++i) {
6375 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6376 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6377 info->is_pinned = header->locals [i]->pinned;
6378 info->local_index = i;
6379 mono_array_setref (ret->locals, i, info);
6383 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6384 for (i = 0; i < header->num_clauses; ++i) {
6385 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6386 MonoExceptionClause *clause = &header->clauses [i];
6388 info->flags = clause->flags;
6389 info->try_offset = clause->try_offset;
6390 info->try_length = clause->try_len;
6391 info->handler_offset = clause->handler_offset;
6392 info->handler_length = clause->handler_len;
6393 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6394 info->filter_offset = clause->data.filter_offset;
6395 else if (clause->data.catch_class)
6396 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6398 mono_array_setref (ret->clauses, i, info);
6401 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6406 * mono_get_dbnull_object:
6407 * @domain: Domain where the object lives
6409 * Returns the System.DBNull.Value singleton object
6411 * Used as the value for ParameterInfo.DefaultValue
6414 mono_get_dbnull_object (MonoDomain *domain)
6417 static MonoClassField *dbnull_value_field = NULL;
6419 if (!dbnull_value_field) {
6420 MonoClass *dbnull_klass;
6421 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6422 mono_class_init (dbnull_klass);
6423 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6424 g_assert (dbnull_value_field);
6426 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6432 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6434 guint32 param_index, i, lastp, crow = 0;
6435 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6438 MonoClass *klass = method->klass;
6439 MonoImage *image = klass->image;
6440 MonoMethodSignature *methodsig = mono_method_signature (method);
6442 MonoTableInfo *constt;
6443 MonoTableInfo *methodt;
6444 MonoTableInfo *paramt;
6446 if (!methodsig->param_count)
6449 mono_class_init (klass);
6451 if (klass->image->dynamic) {
6452 MonoReflectionMethodAux *aux;
6453 if (method->is_inflated)
6454 method = ((MonoMethodInflated*)method)->declaring;
6455 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6456 if (aux && aux->param_defaults) {
6457 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6458 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6463 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6464 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6465 constt = &image->tables [MONO_TABLE_CONSTANT];
6467 idx = mono_method_get_index (method) - 1;
6468 g_assert (idx != -1);
6470 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6471 if (idx + 1 < methodt->rows)
6472 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6474 lastp = paramt->rows + 1;
6476 for (i = param_index; i < lastp; ++i) {
6479 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6480 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6482 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6485 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6490 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6491 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6492 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6499 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6504 MonoType *basetype = type;
6509 klass = mono_class_from_mono_type (type);
6510 if (klass->valuetype) {
6511 object = mono_object_new (domain, klass);
6512 retval = ((gchar *) object + sizeof (MonoObject));
6513 if (klass->enumtype)
6514 basetype = klass->enum_basetype;
6519 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6526 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6530 memset (assembly, 0, sizeof (MonoAssemblyName));
6532 assembly->culture = "";
6533 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6535 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6538 while (g_ascii_isspace (*p) || *p == ',') {
6547 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6549 assembly->major = strtoul (p, &s, 10);
6550 if (s == p || *s != '.')
6553 assembly->minor = strtoul (p, &s, 10);
6554 if (s == p || *s != '.')
6557 assembly->build = strtoul (p, &s, 10);
6558 if (s == p || *s != '.')
6561 assembly->revision = strtoul (p, &s, 10);
6565 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6567 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6568 assembly->culture = "";
6571 assembly->culture = p;
6572 while (*p && *p != ',') {
6576 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6578 if (strncmp (p, "null", 4) == 0) {
6583 while (*p && *p != ',') {
6586 len = (p - start + 1);
6587 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6588 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6589 g_strlcpy ((char*)assembly->public_key_token, start, len);
6592 while (*p && *p != ',')
6596 while (g_ascii_isspace (*p) || *p == ',') {
6610 * mono_reflection_parse_type:
6613 * Parse a type name as accepted by the GetType () method and output the info
6614 * extracted in the info structure.
6615 * the name param will be mangled, so, make a copy before passing it to this function.
6616 * The fields in info will be valid until the memory pointed to by name is valid.
6618 * See also mono_type_get_name () below.
6620 * Returns: 0 on parse error.
6623 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6624 MonoTypeNameParse *info)
6626 char *start, *p, *w, *temp, *last_point, *startn;
6627 int in_modifiers = 0;
6628 int isbyref = 0, rank, arity = 0, i;
6630 start = p = w = name;
6632 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6633 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6634 info->name = info->name_space = NULL;
6635 info->nested = NULL;
6636 info->modifiers = NULL;
6637 info->type_arguments = NULL;
6639 /* last_point separates the namespace from the name */
6645 *p = 0; /* NULL terminate the name */
6647 info->nested = g_list_append (info->nested, startn);
6648 /* we have parsed the nesting namespace + name */
6652 info->name_space = start;
6654 info->name = last_point + 1;
6656 info->name_space = (char *)"";
6675 i = strtol (p, &temp, 10);
6692 info->name_space = start;
6694 info->name = last_point + 1;
6696 info->name_space = (char *)"";
6703 if (isbyref) /* only one level allowed by the spec */
6706 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6710 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6716 info->type_arguments = g_ptr_array_new ();
6717 for (i = 0; i < arity; i++) {
6718 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6719 gboolean fqname = FALSE;
6721 g_ptr_array_add (info->type_arguments, subinfo);
6728 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6739 while (*p && (*p != ']'))
6747 if (g_ascii_isspace (*aname)) {
6754 !assembly_name_to_aname (&subinfo->assembly, aname))
6758 if (i + 1 < arity) {
6778 else if (*p == '*') /* '*' means unknown lower bound */
6779 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6786 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6797 if (g_ascii_isspace (*p)) {
6804 return 0; /* missing assembly name */
6805 if (!assembly_name_to_aname (&info->assembly, p))
6811 if (info->assembly.name)
6814 // *w = 0; /* terminate class name */
6816 if (!info->name || !*info->name)
6820 /* add other consistency checks */
6825 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6827 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6831 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6833 gboolean type_resolve = FALSE;
6835 MonoImage *rootimage = image;
6837 if (info->assembly.name) {
6838 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6839 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
6841 * This could happen in the AOT compiler case when the search hook is not
6844 assembly = image->assembly;
6846 /* then we must load the assembly ourselve - see #60439 */
6847 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6851 image = assembly->image;
6852 } else if (!image) {
6853 image = mono_defaults.corlib;
6856 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6857 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6858 image = mono_defaults.corlib;
6859 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6866 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6871 gboolean bounded = FALSE;
6874 image = mono_defaults.corlib;
6877 klass = mono_class_from_name_case (image, info->name_space, info->name);
6879 klass = mono_class_from_name (image, info->name_space, info->name);
6882 for (mod = info->nested; mod; mod = mod->next) {
6883 gpointer iter = NULL;
6887 mono_class_init (parent);
6889 while ((klass = mono_class_get_nested_types (parent, &iter))) {
6891 if (g_strcasecmp (klass->name, mod->data) == 0)
6894 if (strcmp (klass->name, mod->data) == 0)
6903 mono_class_init (klass);
6905 if (info->type_arguments) {
6906 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6907 MonoReflectionType *the_type;
6911 for (i = 0; i < info->type_arguments->len; i++) {
6912 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6914 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
6915 if (!type_args [i]) {
6921 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6923 instance = mono_reflection_bind_generic_parameters (
6924 the_type, info->type_arguments->len, type_args);
6930 klass = mono_class_from_mono_type (instance);
6933 for (mod = info->modifiers; mod; mod = mod->next) {
6934 modval = GPOINTER_TO_UINT (mod->data);
6935 if (!modval) { /* byref: must be last modifier */
6936 return &klass->this_arg;
6937 } else if (modval == -1) {
6938 klass = mono_ptr_class_get (&klass->byval_arg);
6939 } else if (modval == -2) {
6941 } else { /* array rank */
6942 klass = mono_bounded_array_class_get (klass, modval, bounded);
6944 mono_class_init (klass);
6947 return &klass->byval_arg;
6951 * mono_reflection_get_type:
6952 * @image: a metadata context
6953 * @info: type description structure
6954 * @ignorecase: flag for case-insensitive string compares
6955 * @type_resolve: whenever type resolve was already tried
6957 * Build a MonoType from the type description in @info.
6962 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
6963 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
6967 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
6969 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
6973 g_assert (assembly->dynamic);
6975 /* Enumerate all modules */
6978 if (abuilder->modules) {
6979 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6980 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6981 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
6987 if (!type && abuilder->loaded_modules) {
6988 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6989 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6990 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7000 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7003 MonoReflectionAssembly *assembly;
7007 if (image && image->dynamic)
7008 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7010 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7013 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7020 *type_resolve = TRUE;
7023 /* Reconstruct the type name */
7024 fullName = g_string_new ("");
7025 if (info->name_space && (info->name_space [0] != '\0'))
7026 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7028 g_string_printf (fullName, info->name);
7029 for (mod = info->nested; mod; mod = mod->next)
7030 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7032 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7034 if (assembly->assembly->dynamic)
7035 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7037 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7040 g_string_free (fullName, TRUE);
7045 mono_reflection_free_type_info (MonoTypeNameParse *info)
7047 g_list_free (info->modifiers);
7048 g_list_free (info->nested);
7050 if (info->type_arguments) {
7053 for (i = 0; i < info->type_arguments->len; i++) {
7054 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7056 mono_reflection_free_type_info (subinfo);
7057 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7061 g_ptr_array_free (info->type_arguments, TRUE);
7066 * mono_reflection_type_from_name:
7068 * @image: a metadata context (can be NULL).
7070 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7071 * it defaults to get the type from @image or, if @image is NULL or loading
7072 * from it fails, uses corlib.
7076 mono_reflection_type_from_name (char *name, MonoImage *image)
7078 MonoType *type = NULL;
7079 MonoTypeNameParse info;
7082 /* Make a copy since parse_type modifies its argument */
7083 tmp = g_strdup (name);
7085 /*g_print ("requested type %s\n", str);*/
7086 if (mono_reflection_parse_type (tmp, &info)) {
7087 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7091 mono_reflection_free_type_info (&info);
7096 * mono_reflection_get_token:
7098 * Return the metadata token of OBJ which should be an object
7099 * representing a metadata element.
7102 mono_reflection_get_token (MonoObject *obj)
7107 klass = obj->vtable->klass;
7109 if (strcmp (klass->name, "MethodBuilder") == 0) {
7110 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7112 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7113 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7114 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7116 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7117 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7118 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7120 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7121 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7122 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7123 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7124 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7125 } else if (strcmp (klass->name, "MonoType") == 0) {
7126 MonoReflectionType *tb = (MonoReflectionType *)obj;
7127 token = mono_class_from_mono_type (tb->type)->type_token;
7128 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7129 strcmp (klass->name, "MonoMethod") == 0 ||
7130 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7131 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7132 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7133 if (m->method->is_inflated) {
7134 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7135 return inflated->declaring->token;
7137 token = m->method->token;
7139 } else if (strcmp (klass->name, "MonoField") == 0) {
7140 MonoReflectionField *f = (MonoReflectionField*)obj;
7142 if (f->field->generic_info && f->field->generic_info->reflection_info)
7143 return mono_reflection_get_token (f->field->generic_info->reflection_info);
7145 token = mono_class_get_field_token (f->field);
7146 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7147 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7149 token = mono_class_get_property_token (p->property);
7150 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7151 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7153 token = mono_class_get_event_token (p->event);
7154 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7155 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7157 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7158 } else if (strcmp (klass->name, "Module") == 0) {
7159 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7162 } else if (strcmp (klass->name, "Assembly") == 0) {
7163 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7165 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7166 MonoException *ex = mono_get_exception_not_implemented (msg);
7168 mono_raise_exception (ex);
7175 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7177 int slen, type = t->type;
7178 MonoClass *tklass = t->data.klass;
7184 case MONO_TYPE_BOOLEAN: {
7185 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7190 case MONO_TYPE_CHAR:
7192 case MONO_TYPE_I2: {
7193 guint16 *val = g_malloc (sizeof (guint16));
7198 #if SIZEOF_VOID_P == 4
7204 case MONO_TYPE_I4: {
7205 guint32 *val = g_malloc (sizeof (guint32));
7210 #if SIZEOF_VOID_P == 8
7211 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7215 case MONO_TYPE_I8: {
7216 guint64 *val = g_malloc (sizeof (guint64));
7221 case MONO_TYPE_R8: {
7222 double *val = g_malloc (sizeof (double));
7227 case MONO_TYPE_VALUETYPE:
7228 if (t->data.klass->enumtype) {
7229 type = t->data.klass->enum_basetype->type;
7232 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7235 case MONO_TYPE_STRING:
7236 if (*p == (char)0xFF) {
7240 slen = mono_metadata_decode_value (p, &p);
7242 return mono_string_new_len (mono_domain_get (), p, slen);
7243 case MONO_TYPE_CLASS: {
7246 if (*p == (char)0xFF) {
7251 slen = mono_metadata_decode_value (p, &p);
7252 n = g_memdup (p, slen + 1);
7254 t = mono_reflection_type_from_name (n, image);
7256 g_warning ("Cannot load type '%s'", n);
7260 return mono_type_get_object (mono_domain_get (), t);
7264 case MONO_TYPE_OBJECT: {
7267 MonoClass *subc = NULL;
7272 } else if (subt == 0x0E) {
7273 type = MONO_TYPE_STRING;
7275 } else if (subt == 0x1D) {
7276 MonoType simple_type = {{0}};
7281 /* See Partition II, Appendix B3 */
7282 etype = MONO_TYPE_OBJECT;
7283 type = MONO_TYPE_SZARRAY;
7284 simple_type.type = etype;
7285 tklass = mono_class_from_mono_type (&simple_type);
7287 } else if (subt == 0x55) {
7290 slen = mono_metadata_decode_value (p, &p);
7291 n = g_memdup (p, slen + 1);
7293 t = mono_reflection_type_from_name (n, image);
7295 g_error ("Cannot load type '%s'", n);
7298 subc = mono_class_from_mono_type (t);
7299 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7300 MonoType simple_type = {{0}};
7301 simple_type.type = subt;
7302 subc = mono_class_from_mono_type (&simple_type);
7304 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7306 val = load_cattr_value (image, &subc->byval_arg, p, end);
7307 obj = mono_object_new (mono_domain_get (), subc);
7308 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7312 case MONO_TYPE_SZARRAY: {
7314 guint32 i, alen, basetype;
7317 if (alen == 0xffffffff) {
7321 arr = mono_array_new (mono_domain_get(), tklass, alen);
7322 basetype = tklass->byval_arg.type;
7323 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7324 basetype = tklass->enum_basetype->type;
7329 case MONO_TYPE_BOOLEAN:
7330 for (i = 0; i < alen; i++) {
7331 MonoBoolean val = *p++;
7332 mono_array_set (arr, MonoBoolean, i, val);
7335 case MONO_TYPE_CHAR:
7338 for (i = 0; i < alen; i++) {
7339 guint16 val = read16 (p);
7340 mono_array_set (arr, guint16, i, val);
7347 for (i = 0; i < alen; i++) {
7348 guint32 val = read32 (p);
7349 mono_array_set (arr, guint32, i, val);
7354 for (i = 0; i < alen; i++) {
7357 mono_array_set (arr, double, i, val);
7363 for (i = 0; i < alen; i++) {
7364 guint64 val = read64 (p);
7365 mono_array_set (arr, guint64, i, val);
7369 case MONO_TYPE_CLASS:
7370 case MONO_TYPE_OBJECT:
7371 case MONO_TYPE_STRING:
7372 for (i = 0; i < alen; i++) {
7373 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7374 mono_array_setref (arr, i, item);
7378 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7384 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7390 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7392 static MonoClass *klass;
7393 static MonoMethod *ctor;
7395 void *params [2], *unboxed;
7398 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7400 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7402 params [0] = mono_type_get_object (mono_domain_get (), t);
7404 retval = mono_object_new (mono_domain_get (), klass);
7405 unboxed = mono_object_unbox (retval);
7406 mono_runtime_invoke (ctor, unboxed, params, NULL);
7412 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7414 static MonoClass *klass;
7415 static MonoMethod *ctor;
7417 void *unboxed, *params [2];
7420 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7422 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7425 params [1] = typedarg;
7426 retval = mono_object_new (mono_domain_get (), klass);
7427 unboxed = mono_object_unbox (retval);
7428 mono_runtime_invoke (ctor, unboxed, params, NULL);
7434 type_is_reference (MonoType *type)
7436 switch (type->type) {
7437 case MONO_TYPE_BOOLEAN:
7438 case MONO_TYPE_CHAR:
7451 case MONO_TYPE_VALUETYPE:
7459 free_param_data (MonoMethodSignature *sig, void **params) {
7461 for (i = 0; i < sig->param_count; ++i) {
7462 if (!type_is_reference (sig->params [i]))
7463 g_free (params [i]);
7468 * Find the field index in the metadata FieldDef table.
7471 find_field_index (MonoClass *klass, MonoClassField *field) {
7474 for (i = 0; i < klass->field.count; ++i) {
7475 if (field == &klass->fields [i])
7476 return klass->field.first + 1 + i;
7482 * Find the property index in the metadata Property table.
7485 find_property_index (MonoClass *klass, MonoProperty *property) {
7488 for (i = 0; i < klass->property.count; ++i) {
7489 if (property == &klass->properties [i])
7490 return klass->property.first + 1 + i;
7496 * Find the event index in the metadata Event table.
7499 find_event_index (MonoClass *klass, MonoEvent *event) {
7502 for (i = 0; i < klass->event.count; ++i) {
7503 if (event == &klass->events [i])
7504 return klass->event.first + 1 + i;
7510 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7512 const char *p = (const char*)data;
7514 guint32 i, j, num_named;
7518 mono_class_init (method->klass);
7521 attr = mono_object_new (mono_domain_get (), method->klass);
7522 mono_runtime_invoke (method, attr, NULL, NULL);
7526 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7529 /*g_print ("got attr %s\n", method->klass->name);*/
7531 /* Allocate using alloca so it gets GC tracking */
7532 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7536 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7537 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7541 attr = mono_object_new (mono_domain_get (), method->klass);
7542 mono_runtime_invoke (method, attr, params, NULL);
7543 free_param_data (method->signature, params);
7544 num_named = read16 (named);
7546 for (j = 0; j < num_named; j++) {
7548 char *name, named_type, data_type;
7549 named_type = *named++;
7550 data_type = *named++; /* type of data */
7551 if (data_type == MONO_TYPE_SZARRAY)
7552 data_type = *named++;
7553 if (data_type == MONO_TYPE_ENUM) {
7556 type_len = mono_metadata_decode_blob_size (named, &named);
7557 type_name = g_malloc (type_len + 1);
7558 memcpy (type_name, named, type_len);
7559 type_name [type_len] = 0;
7561 /* FIXME: lookup the type and check type consistency */
7564 name_len = mono_metadata_decode_blob_size (named, &named);
7565 name = g_malloc (name_len + 1);
7566 memcpy (name, named, name_len);
7567 name [name_len] = 0;
7569 if (named_type == 0x53) {
7570 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7571 void *val = load_cattr_value (image, field->type, named, &named);
7572 mono_field_set_value (attr, field, val);
7573 if (!type_is_reference (field->type))
7575 } else if (named_type == 0x54) {
7578 MonoType *prop_type;
7580 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7581 /* can we have more that 1 arg in a custom attr named property? */
7582 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7583 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7584 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7585 mono_property_set_value (prop, attr, pparams, NULL);
7586 if (!type_is_reference (prop_type))
7587 g_free (pparams [0]);
7596 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7598 MonoArray *typedargs, *namedargs;
7599 MonoClass *attrklass;
7600 static MonoMethod *ctor;
7603 const char *p = (const char*)data;
7605 guint32 i, j, num_named;
7608 mono_class_init (method->klass);
7611 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7613 domain = mono_domain_get ();
7615 /* This is for Attributes with no parameters */
7616 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7617 params [0] = mono_method_get_object (domain, method, NULL);
7618 params [1] = params [2] = NULL;
7619 mono_runtime_invoke (method, attr, params, NULL);
7623 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7626 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7630 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7631 MonoObject *obj, *typedarg;
7634 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7635 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7636 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7637 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7638 mono_array_setref (typedargs, i, typedarg);
7640 if (!type_is_reference (mono_method_signature (method)->params [i]))
7645 num_named = read16 (named);
7646 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7648 attrklass = method->klass;
7649 for (j = 0; j < num_named; j++) {
7651 char *name, named_type, data_type;
7652 named_type = *named++;
7653 data_type = *named++; /* type of data */
7654 if (data_type == MONO_TYPE_SZARRAY)
7655 data_type = *named++;
7656 if (data_type == MONO_TYPE_ENUM) {
7659 type_len = mono_metadata_decode_blob_size (named, &named);
7660 type_name = g_malloc (type_len + 1);
7661 memcpy (type_name, named, type_len);
7662 type_name [type_len] = 0;
7664 /* FIXME: lookup the type and check type consistency */
7667 name_len = mono_metadata_decode_blob_size (named, &named);
7668 name = g_malloc (name_len + 1);
7669 memcpy (name, named, name_len);
7670 name [name_len] = 0;
7672 if (named_type == 0x53) {
7673 MonoObject *obj, *typedarg, *namedarg;
7674 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7675 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7677 minfo = mono_field_get_object (domain, NULL, field);
7678 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7679 typedarg = create_cattr_typed_arg (field->type, obj);
7680 namedarg = create_cattr_named_arg (minfo, typedarg);
7681 mono_array_setref (namedargs, j, namedarg);
7682 if (!type_is_reference (field->type))
7684 } else if (named_type == 0x54) {
7685 MonoObject *obj, *typedarg, *namedarg;
7686 MonoType *prop_type;
7688 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7690 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7691 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7692 minfo = mono_property_get_object (domain, NULL, prop);
7693 val = load_cattr_value (image, prop_type, named, &named);
7694 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7695 typedarg = create_cattr_typed_arg (prop_type, obj);
7696 namedarg = create_cattr_named_arg (minfo, typedarg);
7697 mono_array_setref (namedargs, j, namedarg);
7698 if (!type_is_reference (prop_type))
7703 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7704 params [0] = mono_method_get_object (domain, method, NULL);
7705 params [1] = typedargs;
7706 params [2] = namedargs;
7707 mono_runtime_invoke (ctor, attr, params, NULL);
7712 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7718 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7719 for (i = 0; i < cinfo->num_attrs; ++i) {
7720 if (!cinfo->attrs [i].ctor)
7721 /* The cattr type is not finished yet */
7722 /* We should include the type name but cinfo doesn't contain it */
7723 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7724 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7725 mono_array_setref (result, i, attr);
7731 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7738 for (i = 0; i < cinfo->num_attrs; ++i) {
7739 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7743 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7745 for (i = 0; i < cinfo->num_attrs; ++i) {
7746 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7747 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7748 mono_array_setref (result, n, attr);
7756 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7762 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7763 for (i = 0; i < cinfo->num_attrs; ++i) {
7764 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7765 mono_array_setref (result, i, attr);
7771 * mono_custom_attrs_from_index:
7773 * Returns: NULL if no attributes are found or if a loading error occurs.
7776 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7778 guint32 mtoken, i, len;
7779 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7781 MonoCustomAttrInfo *ainfo;
7782 GList *tmp, *list = NULL;
7785 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7787 i = mono_metadata_custom_attrs_from_index (image, idx);
7791 while (i < ca->rows) {
7792 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7794 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7797 len = g_list_length (list);
7800 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7801 ainfo->num_attrs = len;
7802 ainfo->image = image;
7803 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7804 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7805 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7806 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7807 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7808 mtoken |= MONO_TOKEN_METHOD_DEF;
7810 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7811 mtoken |= MONO_TOKEN_MEMBER_REF;
7814 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7817 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7818 if (!ainfo->attrs [i].ctor) {
7819 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7824 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7825 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7826 ainfo->attrs [i].data = (guchar*)data;
7834 mono_custom_attrs_from_method (MonoMethod *method)
7839 * An instantiated method has the same cattrs as the generic method definition.
7841 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7842 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7844 if (method->is_inflated)
7845 method = ((MonoMethodInflated *) method)->declaring;
7847 if (method->dynamic || method->klass->image->dynamic)
7848 return lookup_custom_attr (method->klass->image, method);
7850 idx = mono_method_get_index (method);
7851 idx <<= MONO_CUSTOM_ATTR_BITS;
7852 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7853 return mono_custom_attrs_from_index (method->klass->image, idx);
7857 mono_custom_attrs_from_class (MonoClass *klass)
7861 if (klass->generic_class)
7862 klass = klass->generic_class->container_class;
7864 if (klass->image->dynamic)
7865 return lookup_custom_attr (klass->image, klass);
7867 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
7868 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
7869 idx <<= MONO_CUSTOM_ATTR_BITS;
7870 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
7872 idx = mono_metadata_token_index (klass->type_token);
7873 idx <<= MONO_CUSTOM_ATTR_BITS;
7874 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7876 return mono_custom_attrs_from_index (klass->image, idx);
7880 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7884 if (assembly->image->dynamic)
7885 return lookup_custom_attr (assembly->image, assembly);
7886 idx = 1; /* there is only one assembly */
7887 idx <<= MONO_CUSTOM_ATTR_BITS;
7888 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7889 return mono_custom_attrs_from_index (assembly->image, idx);
7892 static MonoCustomAttrInfo*
7893 mono_custom_attrs_from_module (MonoImage *image)
7898 return lookup_custom_attr (image, image);
7899 idx = 1; /* there is only one module */
7900 idx <<= MONO_CUSTOM_ATTR_BITS;
7901 idx |= MONO_CUSTOM_ATTR_MODULE;
7902 return mono_custom_attrs_from_index (image, idx);
7906 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7910 if (klass->image->dynamic) {
7911 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
7912 return lookup_custom_attr (klass->image, property);
7914 idx = find_property_index (klass, property);
7915 idx <<= MONO_CUSTOM_ATTR_BITS;
7916 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7917 return mono_custom_attrs_from_index (klass->image, idx);
7921 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7925 if (klass->image->dynamic) {
7926 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
7927 return lookup_custom_attr (klass->image, event);
7929 idx = find_event_index (klass, event);
7930 idx <<= MONO_CUSTOM_ATTR_BITS;
7931 idx |= MONO_CUSTOM_ATTR_EVENT;
7932 return mono_custom_attrs_from_index (klass->image, idx);
7936 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7939 if (klass->image->dynamic) {
7940 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
7941 return lookup_custom_attr (klass->image, field);
7943 idx = find_field_index (klass, field);
7944 idx <<= MONO_CUSTOM_ATTR_BITS;
7945 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7946 return mono_custom_attrs_from_index (klass->image, idx);
7950 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7953 guint32 i, idx, method_index;
7954 guint32 param_list, param_last, param_pos, found;
7956 MonoReflectionMethodAux *aux;
7959 * An instantiated method has the same cattrs as the generic method definition.
7961 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7962 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7964 if (method->is_inflated)
7965 method = ((MonoMethodInflated *) method)->declaring;
7967 if (method->klass->image->dynamic) {
7968 MonoCustomAttrInfo *res, *ainfo;
7971 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7972 if (!aux || !aux->param_cattr)
7975 /* Need to copy since it will be freed later */
7976 ainfo = aux->param_cattr [param];
7977 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7978 res = g_malloc0 (size);
7979 memcpy (res, ainfo, size);
7983 image = method->klass->image;
7984 method_index = mono_method_get_index (method);
7985 ca = &image->tables [MONO_TABLE_METHOD];
7987 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7988 if (method_index == ca->rows) {
7989 ca = &image->tables [MONO_TABLE_PARAM];
7990 param_last = ca->rows + 1;
7992 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7993 ca = &image->tables [MONO_TABLE_PARAM];
7996 for (i = param_list; i < param_last; ++i) {
7997 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7998 if (param_pos == param) {
8006 idx <<= MONO_CUSTOM_ATTR_BITS;
8007 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8008 return mono_custom_attrs_from_index (image, idx);
8012 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8016 for (i = 0; i < ainfo->num_attrs; ++i) {
8017 klass = ainfo->attrs [i].ctor->klass;
8018 if (mono_class_has_parent (klass, attr_klass))
8025 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8032 for (i = 0; i < ainfo->num_attrs; ++i) {
8033 klass = ainfo->attrs [i].ctor->klass;
8034 if (mono_class_has_parent (klass, attr_klass)) {
8039 if (attr_index == -1)
8042 attrs = mono_custom_attrs_construct (ainfo);
8044 return mono_array_get (attrs, MonoObject*, attr_index);
8050 * mono_reflection_get_custom_attrs_info:
8051 * @obj: a reflection object handle
8053 * Return the custom attribute info for attributes defined for the
8054 * reflection handle @obj. The objects.
8057 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8060 MonoCustomAttrInfo *cinfo = NULL;
8062 klass = obj->vtable->klass;
8063 if (klass == mono_defaults.monotype_class) {
8064 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8065 klass = mono_class_from_mono_type (rtype->type);
8066 cinfo = mono_custom_attrs_from_class (klass);
8067 } else if (strcmp ("Assembly", klass->name) == 0) {
8068 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8069 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8070 } else if (strcmp ("Module", klass->name) == 0) {
8071 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8072 cinfo = mono_custom_attrs_from_module (module->image);
8073 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8074 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8075 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8076 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8077 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
8078 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8079 } else if (strcmp ("MonoField", klass->name) == 0) {
8080 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8081 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8082 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8083 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8084 cinfo = mono_custom_attrs_from_method (rmethod->method);
8085 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8086 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8087 cinfo = mono_custom_attrs_from_method (rmethod->method);
8088 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8089 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8090 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8091 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8092 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8093 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8094 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8095 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8096 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8097 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8098 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8099 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8100 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8101 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8102 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8103 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8104 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8105 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8106 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8107 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8108 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8109 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8110 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8111 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8112 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8113 } else { /* handle other types here... */
8114 g_error ("get custom attrs not yet supported for %s", klass->name);
8121 * mono_reflection_get_custom_attrs_by_type:
8122 * @obj: a reflection object handle
8124 * Return an array with all the custom attributes defined of the
8125 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8126 * of that type are returned. The objects are fully build. Return NULL if a loading error
8130 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8133 MonoCustomAttrInfo *cinfo;
8135 cinfo = mono_reflection_get_custom_attrs_info (obj);
8138 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8140 result = mono_custom_attrs_construct (cinfo);
8142 mono_custom_attrs_free (cinfo);
8144 if (mono_loader_get_last_error ())
8146 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8153 * mono_reflection_get_custom_attrs:
8154 * @obj: a reflection object handle
8156 * Return an array with all the custom attributes defined of the
8157 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8161 mono_reflection_get_custom_attrs (MonoObject *obj)
8163 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8167 * mono_reflection_get_custom_attrs_data:
8168 * @obj: a reflection obj handle
8170 * Returns an array of System.Reflection.CustomAttributeData,
8171 * which include information about attributes reflected on
8172 * types loaded using the Reflection Only methods
8175 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8178 MonoCustomAttrInfo *cinfo;
8180 cinfo = mono_reflection_get_custom_attrs_info (obj);
8182 result = mono_custom_attrs_data_construct (cinfo);
8184 mono_custom_attrs_free (cinfo);
8186 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8191 static MonoReflectionType*
8192 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8194 MonoMethod *method_get_underlying_system_type;
8196 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8197 mono_class_get_method_from_name (mono_object_class (t),
8198 "get_UnderlyingSystemType",
8200 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8204 mono_reflection_type_get_handle (MonoReflectionType* t)
8209 t = mono_reflection_type_get_underlying_system_type (t);
8217 * LOCKING: Assumes the loader lock is held.
8219 static MonoMethodSignature*
8220 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
8221 MonoMethodSignature *sig;
8224 count = parameters? mono_array_length (parameters): 0;
8226 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8227 sig->param_count = count;
8228 sig->sentinelpos = -1; /* FIXME */
8229 for (i = 0; i < count; ++i) {
8230 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8231 sig->params [i] = mono_reflection_type_get_handle (pt);
8237 * LOCKING: Assumes the loader lock is held.
8239 static MonoMethodSignature*
8240 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
8241 MonoMethodSignature *sig;
8243 sig = parameters_to_signature (mp, ctor->parameters);
8244 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8245 sig->ret = &mono_defaults.void_class->byval_arg;
8250 * LOCKING: Assumes the loader lock is held.
8252 static MonoMethodSignature*
8253 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
8254 MonoMethodSignature *sig;
8256 sig = parameters_to_signature (mp, method->parameters);
8257 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8258 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8259 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8263 static MonoMethodSignature*
8264 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8265 MonoMethodSignature *sig;
8267 sig = parameters_to_signature (NULL, method->parameters);
8268 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8269 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8270 sig->generic_param_count = 0;
8275 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8277 MonoClass *klass = mono_object_class (prop);
8278 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8279 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8280 *name = mono_string_to_utf8 (pb->name);
8281 *type = pb->type->type;
8283 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8284 *name = g_strdup (p->property->name);
8285 if (p->property->get)
8286 *type = mono_method_signature (p->property->get)->ret;
8288 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8293 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8295 MonoClass *klass = mono_object_class (field);
8296 if (strcmp (klass->name, "FieldBuilder") == 0) {
8297 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8298 *name = mono_string_to_utf8 (fb->name);
8299 *type = fb->type->type;
8301 MonoReflectionField *f = (MonoReflectionField *)field;
8302 *name = g_strdup (f->field->name);
8303 *type = f->field->type;
8308 * Encode a value in a custom attribute stream of bytes.
8309 * The value to encode is either supplied as an object in argument val
8310 * (valuetypes are boxed), or as a pointer to the data in the
8312 * @type represents the type of the value
8313 * @buffer is the start of the buffer
8314 * @p the current position in the buffer
8315 * @buflen contains the size of the buffer and is used to return the new buffer size
8316 * if this needs to be realloced.
8317 * @retbuffer and @retp return the start and the position of the buffer
8320 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8322 MonoTypeEnum simple_type;
8324 if ((p-buffer) + 10 >= *buflen) {
8327 newbuf = g_realloc (buffer, *buflen);
8328 p = newbuf + (p-buffer);
8332 argval = ((char*)arg + sizeof (MonoObject));
8333 simple_type = type->type;
8335 switch (simple_type) {
8336 case MONO_TYPE_BOOLEAN:
8341 case MONO_TYPE_CHAR:
8344 swap_with_size (p, argval, 2, 1);
8350 swap_with_size (p, argval, 4, 1);
8354 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8364 swap_with_size (p, argval, 8, 1);
8370 swap_with_size (p, argval, 8, 1);
8373 case MONO_TYPE_VALUETYPE:
8374 if (type->data.klass->enumtype) {
8375 simple_type = type->data.klass->enum_basetype->type;
8378 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8381 case MONO_TYPE_STRING: {
8388 str = mono_string_to_utf8 ((MonoString*)arg);
8389 slen = strlen (str);
8390 if ((p-buffer) + 10 + slen >= *buflen) {
8394 newbuf = g_realloc (buffer, *buflen);
8395 p = newbuf + (p-buffer);
8398 mono_metadata_encode_value (slen, p, &p);
8399 memcpy (p, str, slen);
8404 case MONO_TYPE_CLASS: {
8412 k = mono_object_class (arg);
8413 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8414 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8415 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8418 if (rt && (rtc = mono_object_class (rt)) &&
8419 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8420 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8421 arg = (MonoObject *) rt;
8424 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8427 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8428 slen = strlen (str);
8429 if ((p-buffer) + 10 + slen >= *buflen) {
8433 newbuf = g_realloc (buffer, *buflen);
8434 p = newbuf + (p-buffer);
8437 mono_metadata_encode_value (slen, p, &p);
8438 memcpy (p, str, slen);
8443 case MONO_TYPE_SZARRAY: {
8445 MonoClass *eclass, *arg_eclass;
8448 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8451 len = mono_array_length ((MonoArray*)arg);
8453 *p++ = (len >> 8) & 0xff;
8454 *p++ = (len >> 16) & 0xff;
8455 *p++ = (len >> 24) & 0xff;
8457 *retbuffer = buffer;
8458 eclass = type->data.klass;
8459 arg_eclass = mono_object_class (arg)->element_class;
8462 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8463 eclass = mono_defaults.object_class;
8465 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8466 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8467 int elsize = mono_class_array_element_size (arg_eclass);
8468 for (i = 0; i < len; ++i) {
8469 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8472 } else if (eclass->valuetype && arg_eclass->valuetype) {
8473 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8474 int elsize = mono_class_array_element_size (eclass);
8475 for (i = 0; i < len; ++i) {
8476 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8480 for (i = 0; i < len; ++i) {
8481 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8486 case MONO_TYPE_OBJECT: {
8492 * The parameter type is 'object' but the type of the actual
8493 * argument is not. So we have to add type information to the blob
8494 * too. This is completely undocumented in the spec.
8498 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8503 klass = mono_object_class (arg);
8505 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8508 } else if (klass->enumtype) {
8510 } else if (klass == mono_defaults.string_class) {
8511 simple_type = MONO_TYPE_STRING;
8514 } else if (klass->rank == 1) {
8516 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8517 /* See Partition II, Appendix B3 */
8520 *p++ = klass->element_class->byval_arg.type;
8521 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8523 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8524 *p++ = simple_type = klass->byval_arg.type;
8527 g_error ("unhandled type in custom attr");
8529 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8530 slen = strlen (str);
8531 if ((p-buffer) + 10 + slen >= *buflen) {
8535 newbuf = g_realloc (buffer, *buflen);
8536 p = newbuf + (p-buffer);
8539 mono_metadata_encode_value (slen, p, &p);
8540 memcpy (p, str, slen);
8543 simple_type = klass->enum_basetype->type;
8547 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8550 *retbuffer = buffer;
8554 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8556 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8557 char *str = type_get_qualified_name (type, NULL);
8558 int slen = strlen (str);
8562 * This seems to be optional...
8565 mono_metadata_encode_value (slen, p, &p);
8566 memcpy (p, str, slen);
8569 } else if (type->type == MONO_TYPE_OBJECT) {
8571 } else if (type->type == MONO_TYPE_CLASS) {
8572 /* it should be a type: encode_cattr_value () has the check */
8575 mono_metadata_encode_value (type->type, p, &p);
8576 if (type->type == MONO_TYPE_SZARRAY)
8577 /* See the examples in Partition VI, Annex B */
8578 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8585 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8588 /* Preallocate a large enough buffer */
8589 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8590 char *str = type_get_qualified_name (type, NULL);
8593 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8594 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8600 len += strlen (name);
8602 if ((p-buffer) + 20 + len >= *buflen) {
8606 newbuf = g_realloc (buffer, *buflen);
8607 p = newbuf + (p-buffer);
8611 encode_field_or_prop_type (type, p, &p);
8613 len = strlen (name);
8614 mono_metadata_encode_value (len, p, &p);
8615 memcpy (p, name, len);
8617 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8619 *retbuffer = buffer;
8623 * mono_reflection_get_custom_attrs_blob:
8624 * @ctor: custom attribute constructor
8625 * @ctorArgs: arguments o the constructor
8631 * Creates the blob of data that needs to be saved in the metadata and that represents
8632 * the custom attributed described by @ctor, @ctorArgs etc.
8633 * Returns: a Byte array representing the blob of data.
8636 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8639 MonoMethodSignature *sig;
8644 MONO_ARCH_SAVE_REGS;
8646 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8647 /* sig is freed later so allocate it in the heap */
8648 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8650 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8653 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8655 p = buffer = g_malloc (buflen);
8656 /* write the prolog */
8659 for (i = 0; i < sig->param_count; ++i) {
8660 arg = mono_array_get (ctorArgs, MonoObject*, i);
8661 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8665 i += mono_array_length (properties);
8667 i += mono_array_length (fields);
8669 *p++ = (i >> 8) & 0xff;
8672 for (i = 0; i < mono_array_length (properties); ++i) {
8676 prop = mono_array_get (properties, gpointer, i);
8677 get_prop_name_and_type (prop, &pname, &ptype);
8678 *p++ = 0x54; /* PROPERTY signature */
8679 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8686 for (i = 0; i < mono_array_length (fields); ++i) {
8690 field = mono_array_get (fields, gpointer, i);
8691 get_field_name_and_type (field, &fname, &ftype);
8692 *p++ = 0x53; /* FIELD signature */
8693 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8698 g_assert (p - buffer <= buflen);
8699 buflen = p - buffer;
8700 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8701 p = mono_array_addr (result, char, 0);
8702 memcpy (p, buffer, buflen);
8704 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8710 static void* reflection_info_desc = NULL;
8711 #define MOVING_GC_REGISTER(addr) do { \
8712 if (!reflection_info_desc) { \
8714 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8716 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8719 #define MOVING_GC_REGISTER(addr)
8723 * mono_reflection_setup_internal_class:
8724 * @tb: a TypeBuilder object
8726 * Creates a MonoClass that represents the TypeBuilder.
8727 * This is a trick that lets us simplify a lot of reflection code
8728 * (and will allow us to support Build and Run assemblies easier).
8731 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8733 MonoClass *klass, *parent;
8735 MONO_ARCH_SAVE_REGS;
8737 mono_loader_lock ();
8740 /* check so we can compile corlib correctly */
8741 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8742 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8743 parent = tb->parent->type->data.klass;
8745 parent = my_mono_class_from_mono_type (tb->parent->type);
8751 /* the type has already being created: it means we just have to change the parent */
8752 if (tb->type.type) {
8753 klass = mono_class_from_mono_type (tb->type.type);
8754 klass->parent = NULL;
8755 /* fool mono_class_setup_parent */
8756 klass->supertypes = NULL;
8757 mono_class_setup_parent (klass, parent);
8758 mono_class_setup_mono_type (klass);
8759 mono_loader_unlock ();
8763 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8765 klass->image = &tb->module->dynamic_image->image;
8767 klass->inited = 1; /* we lie to the runtime */
8768 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8769 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8770 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8771 klass->flags = tb->attrs;
8773 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8775 klass->element_class = klass;
8777 MOVING_GC_REGISTER (&klass->reflection_info);
8778 klass->reflection_info = tb;
8780 /* Put into cache so mono_class_get () will find it */
8781 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8783 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8784 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8786 if (parent != NULL) {
8787 mono_class_setup_parent (klass, parent);
8788 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8789 const char *old_n = klass->name;
8790 /* trick to get relative numbering right when compiling corlib */
8791 klass->name = "BuildingObject";
8792 mono_class_setup_parent (klass, mono_defaults.object_class);
8793 klass->name = old_n;
8796 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8797 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8798 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8799 klass->instance_size = sizeof (MonoObject);
8800 klass->size_inited = 1;
8801 mono_class_setup_vtable_general (klass, NULL, 0);
8804 mono_class_setup_mono_type (klass);
8806 mono_class_setup_supertypes (klass);
8809 * FIXME: handle interfaces.
8812 tb->type.type = &klass->byval_arg;
8814 if (tb->nesting_type) {
8815 g_assert (tb->nesting_type->type);
8816 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8819 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8821 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8823 mono_loader_unlock ();
8827 * mono_reflection_setup_generic_class:
8828 * @tb: a TypeBuilder object
8830 * Setup the generic class before adding the first generic parameter.
8833 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8837 MONO_ARCH_SAVE_REGS;
8839 klass = my_mono_class_from_mono_type (tb->type.type);
8840 if (tb->generic_container)
8843 tb->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
8844 tb->generic_container->owner.klass = klass;
8848 * mono_reflection_create_generic_class:
8849 * @tb: a TypeBuilder object
8851 * Creates the generic class after all generic parameters have been added.
8854 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8859 MONO_ARCH_SAVE_REGS;
8861 klass = my_mono_class_from_mono_type (tb->type.type);
8863 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8865 if (klass->generic_container || (count == 0))
8868 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8870 klass->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
8872 klass->generic_container->owner.klass = klass;
8873 klass->generic_container->type_argc = count;
8874 klass->generic_container->type_params = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericParam) * count);
8876 for (i = 0; i < count; i++) {
8877 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8878 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8879 /*Make sure we are a diferent type instance */
8880 klass->generic_container->type_params [i].owner = klass->generic_container;
8881 klass->generic_container->type_params [i].pklass = NULL;
8883 g_assert (klass->generic_container->type_params [i].owner);
8886 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8890 * mono_reflection_create_internal_class:
8891 * @tb: a TypeBuilder object
8893 * Actually create the MonoClass that is associated with the TypeBuilder.
8896 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8900 MONO_ARCH_SAVE_REGS;
8902 klass = my_mono_class_from_mono_type (tb->type.type);
8904 mono_loader_lock ();
8905 if (klass->enumtype && klass->enum_basetype == NULL) {
8906 MonoReflectionFieldBuilder *fb;
8909 g_assert (tb->fields != NULL);
8910 g_assert (mono_array_length (tb->fields) >= 1);
8912 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8914 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8915 mono_loader_unlock ();
8919 klass->enum_basetype = fb->type->type;
8920 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8921 if (!klass->element_class)
8922 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8925 * get the element_class from the current corlib.
8927 ec = default_class_from_mono_type (klass->enum_basetype);
8928 klass->instance_size = ec->instance_size;
8929 klass->size_inited = 1;
8931 * this is almost safe to do with enums and it's needed to be able
8932 * to create objects of the enum type (for use in SetConstant).
8934 /* FIXME: Does this mean enums can't have method overrides ? */
8935 mono_class_setup_vtable_general (klass, NULL, 0);
8937 mono_loader_unlock ();
8940 static MonoMarshalSpec*
8941 mono_marshal_spec_from_builder (MonoMemPool *mp, MonoAssembly *assembly,
8942 MonoReflectionMarshal *minfo)
8944 MonoMarshalSpec *res;
8946 res = mp_g_new0 (mp, MonoMarshalSpec, 1);
8947 res->native = minfo->type;
8949 switch (minfo->type) {
8950 case MONO_NATIVE_LPARRAY:
8951 res->data.array_data.elem_type = minfo->eltype;
8952 if (minfo->has_size) {
8953 res->data.array_data.param_num = minfo->param_num;
8954 res->data.array_data.num_elem = minfo->count;
8955 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8958 res->data.array_data.param_num = -1;
8959 res->data.array_data.num_elem = -1;
8960 res->data.array_data.elem_mult = -1;
8964 case MONO_NATIVE_BYVALTSTR:
8965 case MONO_NATIVE_BYVALARRAY:
8966 res->data.array_data.num_elem = minfo->count;
8969 case MONO_NATIVE_CUSTOM:
8970 if (minfo->marshaltyperef)
8971 res->data.custom_data.custom_name =
8972 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8974 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8984 MonoReflectionMarshal*
8985 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8986 MonoMarshalSpec *spec)
8988 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8989 MonoReflectionMarshal *minfo;
8992 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8993 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8994 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8995 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8998 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8999 minfo->type = spec->native;
9001 switch (minfo->type) {
9002 case MONO_NATIVE_LPARRAY:
9003 minfo->eltype = spec->data.array_data.elem_type;
9004 minfo->count = spec->data.array_data.num_elem;
9005 minfo->param_num = spec->data.array_data.param_num;
9008 case MONO_NATIVE_BYVALTSTR:
9009 case MONO_NATIVE_BYVALARRAY:
9010 minfo->count = spec->data.array_data.num_elem;
9013 case MONO_NATIVE_CUSTOM:
9014 if (spec->data.custom_data.custom_name) {
9015 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9017 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9019 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9021 if (spec->data.custom_data.cookie)
9022 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9033 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9034 ReflectionMethodBuilder *rmb,
9035 MonoMethodSignature *sig)
9038 MonoMethodNormal *pm;
9039 MonoMarshalSpec **specs;
9040 MonoReflectionMethodAux *method_aux;
9046 * Methods created using a MethodBuilder should have their memory allocated
9047 * inside the image mempool, while dynamic methods should have their memory
9050 dynamic = rmb->refs != NULL;
9051 mp = dynamic ? NULL : klass->image->mempool;
9054 g_assert (!klass->generic_class);
9056 mono_loader_lock ();
9058 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9059 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9060 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
9062 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
9064 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
9066 pm = (MonoMethodNormal*)m;
9068 m->dynamic = dynamic;
9070 m->flags = rmb->attrs;
9071 m->iflags = rmb->iattrs;
9072 m->name = mp_string_to_utf8 (mp, rmb->name);
9075 m->skip_visibility = rmb->skip_visibility;
9077 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9079 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9080 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9083 m->signature->pinvoke = 1;
9084 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9085 m->signature->pinvoke = 1;
9087 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9089 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
9090 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
9092 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9094 if (klass->image->dynamic)
9095 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9097 mono_loader_unlock ();
9100 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9101 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9102 MonoMethodHeader *header;
9104 gint32 max_stack, i;
9105 gint32 num_locals = 0;
9106 gint32 num_clauses = 0;
9110 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9111 code_size = rmb->ilgen->code_len;
9112 max_stack = rmb->ilgen->max_stack;
9113 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9114 if (rmb->ilgen->ex_handlers)
9115 num_clauses = method_count_clauses (rmb->ilgen);
9118 code = mono_array_addr (rmb->code, guint8, 0);
9119 code_size = mono_array_length (rmb->code);
9120 /* we probably need to run a verifier on the code... */
9130 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
9131 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9132 header->code_size = code_size;
9133 header->code = mp_g_malloc (mp, code_size);
9134 memcpy ((char*)header->code, code, code_size);
9135 header->max_stack = max_stack;
9136 header->init_locals = rmb->init_locals;
9137 header->num_locals = num_locals;
9139 for (i = 0; i < num_locals; ++i) {
9140 MonoReflectionLocalBuilder *lb =
9141 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9143 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
9144 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9147 header->num_clauses = num_clauses;
9149 header->clauses = method_encode_clauses (mp, (MonoDynamicImage*)klass->image,
9150 rmb->ilgen, num_clauses);
9153 pm->header = header;
9156 if (rmb->generic_params) {
9157 int count = mono_array_length (rmb->generic_params);
9158 MonoGenericContainer *container;
9160 container = rmb->generic_container;
9162 m->is_generic = TRUE;
9163 mono_method_set_generic_container (m, container);
9165 container->type_argc = count;
9166 container->type_params = mp_g_new0 (mp, MonoGenericParam, count);
9167 container->owner.method = m;
9169 for (i = 0; i < count; i++) {
9170 MonoReflectionGenericParam *gp =
9171 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9173 container->type_params [i] = *gp->type.type->data.generic_param;
9176 if (klass->generic_container) {
9177 container->parent = klass->generic_container;
9178 container->context.class_inst = klass->generic_container->context.class_inst;
9180 container->context.method_inst = mono_get_shared_generic_inst (container);
9184 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9188 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9190 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
9191 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9192 for (i = 0; i < rmb->nrefs; ++i)
9193 data [i + 1] = rmb->refs [i];
9198 /* Parameter info */
9201 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9202 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
9203 for (i = 0; i <= m->signature->param_count; ++i) {
9204 MonoReflectionParamBuilder *pb;
9205 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9206 if ((i > 0) && (pb->attrs)) {
9207 /* Make a copy since it might point to a shared type structure */
9208 m->signature->params [i - 1] = mono_metadata_type_dup (mp, m->signature->params [i - 1]);
9209 m->signature->params [i - 1]->attrs = pb->attrs;
9212 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9213 MonoDynamicImage *assembly;
9214 guint32 idx, def_type, len;
9218 if (!method_aux->param_defaults) {
9219 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
9220 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
9222 assembly = (MonoDynamicImage*)klass->image;
9223 idx = encode_constant (assembly, pb->def_value, &def_type);
9224 /* Copy the data from the blob since it might get realloc-ed */
9225 p = assembly->blob.data + idx;
9226 len = mono_metadata_decode_blob_size (p, &p2);
9228 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
9229 method_aux->param_default_types [i] = def_type;
9230 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9234 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
9236 if (!method_aux->param_cattr)
9237 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
9238 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (mp, klass->image, pb->cattrs);
9244 /* Parameter marshalling */
9247 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9248 MonoReflectionParamBuilder *pb;
9249 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9250 if (pb->marshal_info) {
9252 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
9253 specs [pb->position] =
9254 mono_marshal_spec_from_builder (mp, klass->image->assembly, pb->marshal_info);
9258 if (specs != NULL) {
9260 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9261 method_aux->param_marshall = specs;
9264 if (klass->image->dynamic && method_aux)
9265 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9267 mono_loader_unlock ();
9273 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9275 ReflectionMethodBuilder rmb;
9276 MonoMethodSignature *sig;
9278 mono_loader_lock ();
9279 sig = ctor_builder_to_signature (klass->image->mempool, mb);
9280 mono_loader_unlock ();
9282 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9284 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9285 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9287 /* If we are in a generic class, we might be called multiple times from inflate_method */
9288 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9289 /* ilgen is no longer needed */
9297 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9299 ReflectionMethodBuilder rmb;
9300 MonoMethodSignature *sig;
9302 mono_loader_lock ();
9303 sig = method_builder_to_signature (klass->image->mempool, mb);
9304 mono_loader_unlock ();
9306 reflection_methodbuilder_from_method_builder (&rmb, mb);
9308 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9309 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9311 /* If we are in a generic class, we might be called multiple times from inflate_method */
9312 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9313 /* ilgen is no longer needed */
9319 static MonoClassField*
9320 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9322 MonoClassField *field;
9327 field = g_new0 (MonoClassField, 1);
9329 field->name = mono_string_to_utf8 (fb->name);
9330 if (fb->attrs || fb->modreq || fb->modopt) {
9331 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9332 field->type->attrs = fb->attrs;
9334 g_assert (klass->image->dynamic);
9335 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9336 g_free (field->type);
9337 field->type = custom;
9339 field->type = fb->type->type;
9341 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9342 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
9343 if (fb->offset != -1)
9344 field->offset = fb->offset;
9345 field->parent = klass;
9346 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9348 if (fb->def_value) {
9349 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9350 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9351 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9352 /* Copy the data from the blob since it might get realloc-ed */
9353 p = assembly->blob.data + idx;
9354 len = mono_metadata_decode_blob_size (p, &p2);
9356 field->data = g_malloc (len);
9357 memcpy ((gpointer)field->data, p, len);
9364 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9367 MonoReflectionTypeBuilder *tb = NULL;
9368 gboolean is_dynamic = FALSE;
9372 mono_loader_lock ();
9374 domain = mono_object_domain (type);
9376 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9377 tb = (MonoReflectionTypeBuilder *) type;
9380 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9381 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9383 tb = rgi->generic_type;
9387 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9388 if (tb && tb->generic_container)
9389 mono_reflection_create_generic_class (tb);
9391 klass = mono_class_from_mono_type (type->type);
9392 if (!klass->generic_container) {
9393 mono_loader_unlock ();
9397 if (klass->wastypebuilder) {
9398 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9403 mono_loader_unlock ();
9405 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9407 return &geninst->byval_arg;
9411 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9413 MonoGenericClass *gclass;
9414 MonoGenericInst *inst;
9416 g_assert (klass->generic_container);
9418 inst = mono_metadata_get_generic_inst (type_argc, types);
9419 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9421 return mono_generic_class_get_class (gclass);
9424 MonoReflectionMethod*
9425 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9428 MonoMethod *method, *inflated;
9429 MonoMethodInflated *imethod;
9430 MonoReflectionMethodBuilder *mb = NULL;
9431 MonoGenericContext tmp_context;
9432 MonoGenericInst *ginst;
9433 MonoType **type_argv;
9436 MONO_ARCH_SAVE_REGS;
9437 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9438 MonoReflectionTypeBuilder *tb;
9441 mb = (MonoReflectionMethodBuilder *) rmethod;
9442 tb = (MonoReflectionTypeBuilder *) mb->type;
9443 klass = mono_class_from_mono_type (tb->type.type);
9445 method = methodbuilder_to_mono_method (klass, mb);
9447 method = rmethod->method;
9450 klass = method->klass;
9452 if (method->is_inflated)
9453 method = ((MonoMethodInflated *) method)->declaring;
9455 count = mono_method_signature (method)->generic_param_count;
9456 if (count != mono_array_length (types))
9459 type_argv = g_new0 (MonoType *, count);
9460 for (i = 0; i < count; i++) {
9461 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9462 type_argv [i] = garg->type;
9464 ginst = mono_metadata_get_generic_inst (count, type_argv);
9467 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9468 tmp_context.method_inst = ginst;
9470 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9471 imethod = (MonoMethodInflated *) inflated;
9473 if (method->klass->image->dynamic) {
9474 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9476 * This table maps metadata structures representing inflated methods/fields
9477 * to the reflection objects representing their generic definitions.
9479 mono_loader_lock ();
9480 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9481 mono_loader_unlock ();
9484 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9488 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9490 MonoMethodInflated *imethod;
9491 MonoGenericContext *context;
9495 * With generic code sharing the klass might not be inflated.
9496 * This can happen because classes inflated with their own
9497 * type arguments are "normalized" to the uninflated class.
9499 if (!klass->generic_class)
9502 context = mono_class_get_context (klass);
9504 if (klass->method.count) {
9505 /* Find the already created inflated method */
9506 for (i = 0; i < klass->method.count; ++i) {
9507 g_assert (klass->methods [i]->is_inflated);
9508 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9511 g_assert (i < klass->method.count);
9512 imethod = (MonoMethodInflated*)klass->methods [i];
9514 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9517 if (method->is_generic && method->klass->image->dynamic) {
9518 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9520 mono_loader_lock ();
9521 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9522 mono_loader_unlock ();
9524 return (MonoMethod *) imethod;
9528 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9533 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9535 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9536 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9537 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9539 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9540 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9541 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9542 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9543 method = ((MonoReflectionMethod *) obj)->method;
9545 method = NULL; /* prevent compiler warning */
9546 g_assert_not_reached ();
9549 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9552 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9554 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9555 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9558 MonoGenericClass *gclass;
9559 MonoDynamicGenericClass *dgclass;
9560 MonoClass *klass, *gklass;
9563 MONO_ARCH_SAVE_REGS;
9565 klass = mono_class_from_mono_type (type->type.type);
9566 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9567 gclass = type->type.type->data.generic_class;
9569 g_assert (gclass->is_dynamic);
9570 dgclass = (MonoDynamicGenericClass *) gclass;
9572 if (dgclass->initialized)
9575 gklass = gclass->container_class;
9576 mono_class_init (gklass);
9578 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9579 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9580 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9581 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9582 dgclass->count_events = events ? mono_array_length (events) : 0;
9584 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9585 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9586 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9587 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9588 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9590 for (i = 0; i < dgclass->count_methods; i++) {
9591 MonoObject *obj = mono_array_get (methods, gpointer, i);
9593 dgclass->methods [i] = inflate_method (type, obj);
9596 for (i = 0; i < dgclass->count_ctors; i++) {
9597 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9599 dgclass->ctors [i] = inflate_method (type, obj);
9602 for (i = 0; i < dgclass->count_fields; i++) {
9603 MonoObject *obj = mono_array_get (fields, gpointer, i);
9604 MonoClassField *field, *inflated_field = NULL;
9605 MonoInflatedField *ifield;
9607 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9608 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9609 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9610 field = ((MonoReflectionField *) obj)->field;
9612 field = NULL; /* prevent compiler warning */
9613 g_assert_not_reached ();
9616 ifield = g_new0 (MonoInflatedField, 1);
9617 ifield->generic_type = field->type;
9618 MOVING_GC_REGISTER (&ifield->reflection_info);
9619 ifield->reflection_info = obj;
9621 dgclass->fields [i] = *field;
9622 dgclass->fields [i].parent = klass;
9623 dgclass->fields [i].generic_info = ifield;
9624 dgclass->fields [i].type = mono_class_inflate_generic_type (
9625 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9627 if (inflated_field) {
9628 g_free ((char*)inflated_field->data);
9629 g_free (inflated_field);
9631 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9635 for (i = 0; i < dgclass->count_properties; i++) {
9636 MonoObject *obj = mono_array_get (properties, gpointer, i);
9637 MonoProperty *property = &dgclass->properties [i];
9639 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9640 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9642 property->parent = klass;
9643 property->attrs = pb->attrs;
9644 property->name = mono_string_to_utf8 (pb->name);
9646 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9648 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9649 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9650 *property = *((MonoReflectionProperty *) obj)->property;
9651 property->name = g_strdup (property->name);
9654 property->get = inflate_mono_method (klass, property->get, NULL);
9656 property->set = inflate_mono_method (klass, property->set, NULL);
9658 g_assert_not_reached ();
9661 for (i = 0; i < dgclass->count_events; i++) {
9662 MonoObject *obj = mono_array_get (events, gpointer, i);
9663 MonoEvent *event = &dgclass->events [i];
9665 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9666 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9668 event->parent = klass;
9669 event->attrs = eb->attrs;
9670 event->name = mono_string_to_utf8 (eb->name);
9672 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9673 if (eb->remove_method)
9674 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9675 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9676 *event = *((MonoReflectionEvent *) obj)->event;
9677 event->name = g_strdup (event->name);
9680 event->add = inflate_mono_method (klass, event->add, NULL);
9682 event->remove = inflate_mono_method (klass, event->remove, NULL);
9684 g_assert_not_reached ();
9687 dgclass->initialized = TRUE;
9691 ensure_runtime_vtable (MonoClass *klass)
9693 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9696 if (!tb || klass->wastypebuilder)
9699 ensure_runtime_vtable (klass->parent);
9701 num = tb->ctors? mono_array_length (tb->ctors): 0;
9702 num += tb->num_methods;
9703 klass->method.count = num;
9704 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9705 num = tb->ctors? mono_array_length (tb->ctors): 0;
9706 for (i = 0; i < num; ++i)
9707 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9708 num = tb->num_methods;
9710 for (i = 0; i < num; ++i)
9711 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9713 if (tb->interfaces) {
9714 klass->interface_count = mono_array_length (tb->interfaces);
9715 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9716 for (i = 0; i < klass->interface_count; ++i) {
9717 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9718 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9722 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9723 for (i = 0; i < klass->method.count; ++i)
9724 klass->methods [i]->slot = i;
9726 mono_class_setup_interface_offsets (klass);
9730 * The generic vtable is needed even if image->run is not set since some
9731 * runtime code like ves_icall_Type_GetMethodsByName depends on
9732 * method->slot being defined.
9736 * tb->methods could not be freed since it is used for determining
9737 * overrides during dynamic vtable construction.
9742 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9744 MonoReflectionTypeBuilder *tb;
9750 g_assert (klass->image->dynamic);
9752 if (!klass->reflection_info)
9755 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9757 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9761 for (i = 0; i < tb->num_methods; ++i) {
9762 MonoReflectionMethodBuilder *mb =
9763 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9764 if (mb->override_method)
9770 *overrides = g_new0 (MonoMethod*, onum * 2);
9773 for (i = 0; i < tb->num_methods; ++i) {
9774 MonoReflectionMethodBuilder *mb =
9775 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9776 if (mb->override_method) {
9777 (*overrides) [onum * 2] =
9778 mb->override_method->method;
9779 (*overrides) [onum * 2 + 1] =
9782 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9783 g_assert (mb->override_method->method);
9784 g_assert (mb->mhandle);
9791 *num_overrides = onum;
9795 typebuilder_setup_fields (MonoClass *klass)
9797 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9798 MonoReflectionFieldBuilder *fb;
9799 MonoClassField *field;
9800 MonoMemPool *mp = klass->image->mempool;
9803 guint32 len, idx, real_size = 0;
9805 klass->field.count = tb->num_fields;
9806 klass->field.first = 0;
9808 if (tb->class_size) {
9809 g_assert ((tb->packing_size & 0xfffffff0) == 0);
9810 klass->packing_size = tb->packing_size;
9811 real_size = klass->instance_size + tb->class_size;
9814 if (!klass->field.count) {
9815 klass->instance_size = MAX (klass->instance_size, real_size);
9819 klass->fields = mp_g_new0 (mp, MonoClassField, klass->field.count);
9821 for (i = 0; i < klass->field.count; ++i) {
9822 fb = mono_array_get (tb->fields, gpointer, i);
9823 field = &klass->fields [i];
9824 field->name = mp_string_to_utf8 (mp, fb->name);
9826 field->type = mono_metadata_type_dup (mp, fb->type->type);
9827 field->type->attrs = fb->attrs;
9829 field->type = fb->type->type;
9831 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9832 field->data = mono_array_addr (fb->rva_data, char, 0);
9833 if (fb->offset != -1)
9834 field->offset = fb->offset;
9835 field->parent = klass;
9837 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9839 if (fb->def_value) {
9840 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9841 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9842 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9843 /* Copy the data from the blob since it might get realloc-ed */
9844 p = assembly->blob.data + idx;
9845 len = mono_metadata_decode_blob_size (p, &p2);
9847 field->data = mono_mempool_alloc (mp, len);
9848 memcpy ((gpointer)field->data, p, len);
9852 klass->instance_size = MAX (klass->instance_size, real_size);
9853 mono_class_layout_fields (klass);
9857 typebuilder_setup_properties (MonoClass *klass)
9859 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9860 MonoReflectionPropertyBuilder *pb;
9861 MonoMemPool *mp = klass->image->mempool;
9864 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9865 klass->property.first = 0;
9867 klass->properties = mp_g_new0 (mp, MonoProperty, klass->property.count);
9868 for (i = 0; i < klass->property.count; ++i) {
9869 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9870 klass->properties [i].parent = klass;
9871 klass->properties [i].attrs = pb->attrs;
9872 klass->properties [i].name = mp_string_to_utf8 (mp, pb->name);
9874 klass->properties [i].get = pb->get_method->mhandle;
9876 klass->properties [i].set = pb->set_method->mhandle;
9878 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9882 MonoReflectionEvent *
9883 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9885 MonoEvent *event = g_new0 (MonoEvent, 1);
9889 klass = my_mono_class_from_mono_type (tb->type.type);
9891 event->parent = klass;
9892 event->attrs = eb->attrs;
9893 event->name = mono_string_to_utf8 (eb->name);
9895 event->add = eb->add_method->mhandle;
9896 if (eb->remove_method)
9897 event->remove = eb->remove_method->mhandle;
9898 if (eb->raise_method)
9899 event->raise = eb->raise_method->mhandle;
9901 if (eb->other_methods) {
9902 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9903 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9904 MonoReflectionMethodBuilder *mb =
9905 mono_array_get (eb->other_methods,
9906 MonoReflectionMethodBuilder*, j);
9907 event->other [j] = mb->mhandle;
9911 return mono_event_get_object (mono_object_domain (tb), klass, event);
9915 typebuilder_setup_events (MonoClass *klass)
9917 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9918 MonoReflectionEventBuilder *eb;
9919 MonoMemPool *mp = klass->image->mempool;
9922 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9923 klass->event.first = 0;
9925 klass->events = mp_g_new0 (mp, MonoEvent, klass->event.count);
9926 for (i = 0; i < klass->event.count; ++i) {
9927 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9928 klass->events [i].parent = klass;
9929 klass->events [i].attrs = eb->attrs;
9930 klass->events [i].name = mp_string_to_utf8 (mp, eb->name);
9932 klass->events [i].add = eb->add_method->mhandle;
9933 if (eb->remove_method)
9934 klass->events [i].remove = eb->remove_method->mhandle;
9935 if (eb->raise_method)
9936 klass->events [i].raise = eb->raise_method->mhandle;
9938 if (eb->other_methods) {
9939 klass->events [i].other = mp_g_new0 (mp, MonoMethod*, mono_array_length (eb->other_methods) + 1);
9940 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9941 MonoReflectionMethodBuilder *mb =
9942 mono_array_get (eb->other_methods,
9943 MonoReflectionMethodBuilder*, j);
9944 klass->events [i].other [j] = mb->mhandle;
9947 mono_save_custom_attrs (klass->image, &klass->events [i], eb->cattrs);
9952 remove_instantiations_of (gpointer key,
9956 MonoType *type = (MonoType*)key;
9957 MonoClass *klass = (MonoClass*)user_data;
9959 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
9966 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9970 MonoReflectionType* res;
9973 MONO_ARCH_SAVE_REGS;
9975 domain = mono_object_domain (tb);
9976 klass = my_mono_class_from_mono_type (tb->type.type);
9978 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9981 * we need to lock the domain because the lock will be taken inside
9982 * So, we need to keep the locking order correct.
9984 mono_domain_lock (domain);
9985 mono_loader_lock ();
9986 if (klass->wastypebuilder) {
9987 mono_loader_unlock ();
9988 mono_domain_unlock (domain);
9989 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9992 * Fields to set in klass:
9993 * the various flags: delegate/unicode/contextbound etc.
9995 klass->flags = tb->attrs;
9996 klass->has_cctor = 1;
9997 klass->has_finalize = 1;
10000 if (!((MonoDynamicImage*)klass->image)->run) {
10001 if (klass->generic_container) {
10002 /* FIXME: The code below can't handle generic classes */
10003 klass->wastypebuilder = TRUE;
10004 mono_loader_unlock ();
10005 mono_domain_unlock (domain);
10006 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10011 /* enums are done right away */
10012 if (!klass->enumtype)
10013 ensure_runtime_vtable (klass);
10015 if (tb->subtypes) {
10016 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10017 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10018 klass->nested_classes = g_list_prepend_mempool (klass->image->mempool, klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
10022 klass->nested_classes_inited = TRUE;
10024 /* fields and object layout */
10025 if (klass->parent) {
10026 if (!klass->parent->size_inited)
10027 mono_class_init (klass->parent);
10028 klass->instance_size = klass->parent->instance_size;
10029 klass->sizes.class_size = 0;
10030 klass->min_align = klass->parent->min_align;
10031 /* if the type has no fields we won't call the field_setup
10032 * routine which sets up klass->has_references.
10034 klass->has_references |= klass->parent->has_references;
10036 klass->instance_size = sizeof (MonoObject);
10037 klass->min_align = 1;
10040 /* FIXME: handle packing_size and instance_size */
10041 typebuilder_setup_fields (klass);
10043 typebuilder_setup_properties (klass);
10045 typebuilder_setup_events (klass);
10047 klass->wastypebuilder = TRUE;
10050 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10051 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10052 * we want to return normal System.MonoType objects, so clear these out from the cache.
10054 if (domain->type_hash && klass->generic_container)
10055 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10057 mono_loader_unlock ();
10058 mono_domain_unlock (domain);
10060 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10061 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10062 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10065 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10066 g_assert (res != (MonoReflectionType*)tb);
10072 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10074 MonoGenericParam *param;
10077 MONO_ARCH_SAVE_REGS;
10079 param = g_new0 (MonoGenericParam, 1);
10081 if (gparam->mbuilder) {
10082 if (!gparam->mbuilder->generic_container) {
10083 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10084 MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
10085 gparam->mbuilder->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
10086 gparam->mbuilder->generic_container->is_method = TRUE;
10088 param->owner = gparam->mbuilder->generic_container;
10089 } else if (gparam->tbuilder) {
10090 g_assert (gparam->tbuilder->generic_container);
10091 param->owner = gparam->tbuilder->generic_container;
10094 param->name = mono_string_to_utf8 (gparam->name);
10095 param->num = gparam->index;
10097 image = &gparam->tbuilder->module->dynamic_image->image;
10098 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10100 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
10101 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10103 gparam->type.type = g_new0 (MonoType, 1);
10104 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
10105 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
10106 gparam->type.type->data.generic_param = param;
10110 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10112 MonoDynamicImage *assembly = sig->module->dynamic_image;
10113 guint32 na = mono_array_length (sig->arguments);
10118 sigbuffer_init (&buf, 32);
10120 sigbuffer_add_value (&buf, 0x07);
10121 sigbuffer_add_value (&buf, na);
10122 for (i = 0; i < na; ++i) {
10123 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10124 encode_reflection_type (assembly, type, &buf);
10127 buflen = buf.p - buf.buf;
10128 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10129 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10130 sigbuffer_free (&buf);
10136 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10138 MonoDynamicImage *assembly = sig->module->dynamic_image;
10139 guint32 na = mono_array_length (sig->arguments);
10144 sigbuffer_init (&buf, 32);
10146 sigbuffer_add_value (&buf, 0x06);
10147 for (i = 0; i < na; ++i) {
10148 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10149 encode_reflection_type (assembly, type, &buf);
10152 buflen = buf.p - buf.buf;
10153 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10154 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10155 sigbuffer_free (&buf);
10161 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10163 ReflectionMethodBuilder rmb;
10164 MonoMethodSignature *sig;
10169 sig = dynamic_method_to_signature (mb);
10171 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10174 * Resolve references.
10177 * Every second entry in the refs array is reserved for storing handle_class,
10178 * which is needed by the ldtoken implementation in the JIT.
10180 rmb.nrefs = mb->nrefs;
10181 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10182 for (i = 0; i < mb->nrefs; i += 2) {
10183 MonoClass *handle_class;
10185 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10187 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10188 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10190 * The referenced DynamicMethod should already be created by the managed
10191 * code, except in the case of circular references. In that case, we store
10192 * method in the refs array, and fix it up later when the referenced
10193 * DynamicMethod is created.
10195 if (method->mhandle) {
10196 ref = method->mhandle;
10198 /* FIXME: GC object stored in unmanaged memory */
10201 /* FIXME: GC object stored in unmanaged memory */
10202 method->referenced_by = g_slist_append (method->referenced_by, mb);
10204 handle_class = mono_defaults.methodhandle_class;
10206 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10209 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10214 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10215 rmb.refs [i + 1] = handle_class;
10218 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10220 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10222 /* Fix up refs entries pointing at us */
10223 for (l = mb->referenced_by; l; l = l->next) {
10224 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10225 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10228 g_assert (method->mhandle);
10230 data = (gpointer*)wrapper->method_data;
10231 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10232 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10233 data [i + 1] = mb->mhandle;
10236 g_slist_free (mb->referenced_by);
10240 /* ilgen is no longer needed */
10245 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10250 mono_runtime_free_method (
10251 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10256 * mono_reflection_is_valid_dynamic_token:
10258 * Returns TRUE if token is valid.
10262 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10264 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10268 * mono_reflection_lookup_dynamic_token:
10270 * Finish the Builder object pointed to by TOKEN and return the corresponding
10271 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10272 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10276 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10278 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10282 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10285 g_assert_not_reached ();
10291 handle_class = &klass;
10292 return resolve_object (image, obj, handle_class, context);
10296 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10298 gpointer result = NULL;
10300 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10301 result = mono_string_intern ((MonoString*)obj);
10302 *handle_class = NULL;
10304 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10305 MonoReflectionType *tb = (MonoReflectionType*)obj;
10307 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10308 result = mono_class_from_mono_type (inflated);
10309 mono_metadata_free_type (inflated);
10311 result = mono_class_from_mono_type (tb->type);
10313 *handle_class = mono_defaults.typehandle_class;
10315 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10316 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10317 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10318 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10319 result = ((MonoReflectionMethod*)obj)->method;
10321 result = mono_class_inflate_generic_method (result, context);
10322 *handle_class = mono_defaults.methodhandle_class;
10324 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10325 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10326 result = mb->mhandle;
10328 /* Type is not yet created */
10329 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10331 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10334 * Hopefully this has been filled in by calling CreateType() on the
10338 * TODO: This won't work if the application finishes another
10339 * TypeBuilder instance instead of this one.
10341 result = mb->mhandle;
10344 result = mono_class_inflate_generic_method (result, context);
10345 *handle_class = mono_defaults.methodhandle_class;
10346 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10347 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10349 result = cb->mhandle;
10351 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10353 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10354 result = cb->mhandle;
10357 result = mono_class_inflate_generic_method (result, context);
10358 *handle_class = mono_defaults.methodhandle_class;
10359 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10360 result = ((MonoReflectionField*)obj)->field;
10361 *handle_class = mono_defaults.fieldhandle_class;
10363 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10364 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10365 result = fb->handle;
10368 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10370 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10371 result = fb->handle;
10374 if (fb->handle && fb->handle->parent->generic_container) {
10375 MonoClass *klass = fb->handle->parent;
10376 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10377 MonoClass *inflated = mono_class_from_mono_type (type);
10379 result = mono_class_get_field_from_name (inflated, fb->handle->name);
10381 mono_metadata_free_type (type);
10383 *handle_class = mono_defaults.fieldhandle_class;
10384 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10385 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10388 klass = tb->type.type->data.klass;
10389 if (klass->wastypebuilder) {
10390 /* Already created */
10394 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10395 result = tb->type.type->data.klass;
10398 *handle_class = mono_defaults.typehandle_class;
10399 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10400 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10401 MonoMethodSignature *sig;
10404 if (helper->arguments)
10405 nargs = mono_array_length (helper->arguments);
10409 sig = mono_metadata_signature_alloc (image, nargs);
10410 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10411 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10413 if (helper->call_conv == 0) /* unmanaged */
10414 sig->call_convention = helper->unmanaged_call_conv - 1;
10416 if (helper->call_conv & 0x02)
10417 sig->call_convention = MONO_CALL_VARARG;
10419 sig->call_convention = MONO_CALL_DEFAULT;
10421 sig->param_count = nargs;
10422 /* TODO: Copy type ? */
10423 sig->ret = helper->return_type->type;
10424 for (i = 0; i < nargs; ++i) {
10425 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10426 sig->params [i] = rt->type;
10430 *handle_class = NULL;
10431 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10432 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10433 /* Already created by the managed code */
10434 g_assert (method->mhandle);
10435 result = method->mhandle;
10436 *handle_class = mono_defaults.methodhandle_class;
10437 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10438 MonoReflectionType *tb = (MonoReflectionType*)obj;
10439 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10440 result = mono_class_from_mono_type (type);
10441 *handle_class = mono_defaults.typehandle_class;
10443 mono_metadata_free_type (type);
10444 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10445 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10446 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10447 result = mono_class_from_mono_type (type);
10448 *handle_class = mono_defaults.typehandle_class;
10450 mono_metadata_free_type (type);
10451 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10452 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10453 MonoClass *inflated;
10456 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10457 inflated = mono_class_from_mono_type (type);
10459 g_assert (f->fb->handle);
10460 result = mono_class_get_field_from_name (inflated, f->fb->handle->name);
10462 mono_metadata_free_type (type);
10463 *handle_class = mono_defaults.fieldhandle_class;
10464 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10465 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10466 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10467 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10468 g_assert (c->cb->mhandle);
10469 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10470 *handle_class = mono_defaults.methodhandle_class;
10471 mono_metadata_free_type (type);
10472 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10473 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10474 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10475 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10476 g_assert (m->mb->mhandle);
10477 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10478 *handle_class = mono_defaults.methodhandle_class;
10479 mono_metadata_free_type (type);
10481 g_print (obj->vtable->klass->name);
10482 g_assert_not_reached ();
10488 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10489 const static guint32 declsec_flags_map[] = {
10490 0x00000000, /* empty */
10491 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10492 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10493 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10494 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10495 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10496 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10497 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10498 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10499 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10500 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10501 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10502 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10503 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10504 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10505 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10506 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10507 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10508 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10512 * Returns flags that includes all available security action associated to the handle.
10513 * @token: metadata token (either for a class or a method)
10514 * @image: image where resides the metadata.
10517 mono_declsec_get_flags (MonoImage *image, guint32 token)
10519 int index = mono_metadata_declsec_from_index (image, token);
10520 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10521 guint32 result = 0;
10525 /* HasSecurity can be present for other, not specially encoded, attributes,
10526 e.g. SuppressUnmanagedCodeSecurityAttribute */
10530 for (i = index; i < t->rows; i++) {
10531 guint32 cols [MONO_DECL_SECURITY_SIZE];
10533 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10534 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10537 action = cols [MONO_DECL_SECURITY_ACTION];
10538 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10539 result |= declsec_flags_map [action];
10541 g_assert_not_reached ();
10548 * Get the security actions (in the form of flags) associated with the specified method.
10550 * @method: The method for which we want the declarative security flags.
10551 * Return the declarative security flags for the method (only).
10553 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10554 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10557 mono_declsec_flags_from_method (MonoMethod *method)
10559 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10560 /* FIXME: No cache (for the moment) */
10561 guint32 idx = mono_method_get_index (method);
10562 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10563 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10564 return mono_declsec_get_flags (method->klass->image, idx);
10570 * Get the security actions (in the form of flags) associated with the specified class.
10572 * @klass: The class for which we want the declarative security flags.
10573 * Return the declarative security flags for the class.
10575 * Note: We cache the flags inside the MonoClass structure as this will get
10576 * called very often (at least for each method).
10579 mono_declsec_flags_from_class (MonoClass *klass)
10581 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10582 if (!klass->declsec_flags) {
10583 guint32 idx = mono_metadata_token_index (klass->type_token);
10584 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10585 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10586 /* we cache the flags on classes */
10587 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10589 return klass->declsec_flags;
10595 * Get the security actions (in the form of flags) associated with the specified assembly.
10597 * @assembly: The assembly for which we want the declarative security flags.
10598 * Return the declarative security flags for the assembly.
10601 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10603 guint32 idx = 1; /* there is only one assembly */
10604 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10605 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10606 return mono_declsec_get_flags (assembly->image, idx);
10611 * Fill actions for the specific index (which may either be an encoded class token or
10612 * an encoded method token) from the metadata image.
10613 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10616 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10617 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10619 MonoBoolean result = FALSE;
10621 guint32 cols [MONO_DECL_SECURITY_SIZE];
10622 int index = mono_metadata_declsec_from_index (image, token);
10625 t = &image->tables [MONO_TABLE_DECLSECURITY];
10626 for (i = index; i < t->rows; i++) {
10627 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10629 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10632 /* if present only replace (class) permissions with method permissions */
10633 /* if empty accept either class or method permissions */
10634 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10635 if (!actions->demand.blob) {
10636 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10637 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10638 actions->demand.blob = (char*) (blob + 2);
10639 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10642 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10643 if (!actions->noncasdemand.blob) {
10644 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10645 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10646 actions->noncasdemand.blob = (char*) (blob + 2);
10647 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10650 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10651 if (!actions->demandchoice.blob) {
10652 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10653 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10654 actions->demandchoice.blob = (char*) (blob + 2);
10655 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10665 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
10666 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10668 guint32 idx = mono_metadata_token_index (klass->type_token);
10669 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10670 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10671 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
10675 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
10676 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10678 guint32 idx = mono_method_get_index (method);
10679 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10680 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10681 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10685 * Collect all actions (that requires to generate code in mini) assigned for
10686 * the specified method.
10687 * Note: Don't use the content of actions if the function return FALSE.
10690 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10692 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
10693 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10694 MonoBoolean result = FALSE;
10697 /* quick exit if no declarative security is present in the metadata */
10698 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10701 /* we want the original as the wrapper is "free" of the security informations */
10702 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10703 method = mono_marshal_method_from_wrapper (method);
10708 /* First we look for method-level attributes */
10709 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10710 mono_class_init (method->klass);
10711 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10713 result = mono_declsec_get_method_demands_params (method, demands,
10714 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10717 /* Here we use (or create) the class declarative cache to look for demands */
10718 flags = mono_declsec_flags_from_class (method->klass);
10719 if (flags & mask) {
10721 mono_class_init (method->klass);
10722 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10724 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10725 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10728 /* The boolean return value is used as a shortcut in case nothing needs to
10729 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10735 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10737 * Note: Don't use the content of actions if the function return FALSE.
10740 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10742 MonoBoolean result = FALSE;
10745 /* quick exit if no declarative security is present in the metadata */
10746 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10749 /* we want the original as the wrapper is "free" of the security informations */
10750 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10751 method = mono_marshal_method_from_wrapper (method);
10756 /* results are independant - zeroize both */
10757 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10758 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10760 /* First we look for method-level attributes */
10761 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10762 mono_class_init (method->klass);
10764 result = mono_declsec_get_method_demands_params (method, cmethod,
10765 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10768 /* Here we use (or create) the class declarative cache to look for demands */
10769 flags = mono_declsec_flags_from_class (method->klass);
10770 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10771 mono_class_init (method->klass);
10773 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10774 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10781 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10783 * @klass The inherited class - this is the class that provides the security check (attributes)
10785 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10787 * Note: Don't use the content of actions if the function return FALSE.
10790 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10792 MonoBoolean result = FALSE;
10795 /* quick exit if no declarative security is present in the metadata */
10796 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10799 /* Here we use (or create) the class declarative cache to look for demands */
10800 flags = mono_declsec_flags_from_class (klass);
10801 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10802 mono_class_init (klass);
10803 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10805 result |= mono_declsec_get_class_demands_params (klass, demands,
10806 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10813 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10815 * Note: Don't use the content of actions if the function return FALSE.
10818 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10820 /* quick exit if no declarative security is present in the metadata */
10821 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10824 /* we want the original as the wrapper is "free" of the security informations */
10825 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10826 method = mono_marshal_method_from_wrapper (method);
10831 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10832 mono_class_init (method->klass);
10833 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10835 return mono_declsec_get_method_demands_params (method, demands,
10836 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10843 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10845 guint32 cols [MONO_DECL_SECURITY_SIZE];
10849 int index = mono_metadata_declsec_from_index (image, token);
10853 t = &image->tables [MONO_TABLE_DECLSECURITY];
10854 for (i = index; i < t->rows; i++) {
10855 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10857 /* shortcut - index are ordered */
10858 if (token != cols [MONO_DECL_SECURITY_PARENT])
10861 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10862 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10863 entry->blob = (char*) (metadata + 2);
10864 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10873 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10875 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10876 guint32 idx = mono_method_get_index (method);
10877 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10878 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10879 return get_declsec_action (method->klass->image, idx, action, entry);
10885 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10888 guint32 flags = mono_declsec_flags_from_class (klass);
10889 if (declsec_flags_map [action] & flags) {
10890 guint32 idx = mono_metadata_token_index (klass->type_token);
10891 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10892 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10893 return get_declsec_action (klass->image, idx, action, entry);
10899 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10901 guint32 idx = 1; /* there is only one assembly */
10902 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10903 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10905 return get_declsec_action (assembly->image, idx, action, entry);
10909 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10911 MonoObject *res, *exc;
10913 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10914 static MonoMethod *method = NULL;
10916 if (!System_Reflection_Emit_TypeBuilder) {
10917 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10918 g_assert (System_Reflection_Emit_TypeBuilder);
10920 if (method == NULL) {
10921 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10926 * The result of mono_type_get_object () might be a System.MonoType but we
10927 * need a TypeBuilder so use klass->reflection_info.
10929 g_assert (klass->reflection_info);
10930 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10932 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10934 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10938 return *(MonoBoolean*)mono_object_unbox (res);