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 encode_type (assembly, type, &buf);
1609 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1610 sigbuffer_free (&buf);
1615 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1620 sigbuffer_init (&buf, 32);
1622 sigbuffer_add_value (&buf, 0x06);
1623 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1624 /* encode custom attributes before the type */
1625 encode_reflection_type (assembly, fb->type, &buf);
1626 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1627 sigbuffer_free (&buf);
1632 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1633 char blob_size [64];
1634 char *b = blob_size;
1637 guint32 idx = 0, len = 0, dummy = 0;
1639 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1640 guint32 fpa_double [2];
1645 p = buf = g_malloc (64);
1647 *ret_type = MONO_TYPE_CLASS;
1649 box_val = (char*)&dummy;
1651 box_val = ((char*)val) + sizeof (MonoObject);
1652 *ret_type = val->vtable->klass->byval_arg.type;
1655 switch (*ret_type) {
1656 case MONO_TYPE_BOOLEAN:
1661 case MONO_TYPE_CHAR:
1678 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1679 fpa_p = (guint32*)box_val;
1680 fpa_double [0] = fpa_p [1];
1681 fpa_double [1] = fpa_p [0];
1682 box_val = (char*)fpa_double;
1686 case MONO_TYPE_VALUETYPE:
1687 if (val->vtable->klass->enumtype) {
1688 *ret_type = val->vtable->klass->enum_basetype->type;
1691 g_error ("we can't encode valuetypes");
1692 case MONO_TYPE_CLASS:
1694 case MONO_TYPE_STRING: {
1695 MonoString *str = (MonoString*)val;
1696 /* there is no signature */
1697 len = str->length * 2;
1698 mono_metadata_encode_value (len, b, &b);
1699 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1701 char *swapped = g_malloc (2 * mono_string_length (str));
1702 const char *p = (const char*)mono_string_chars (str);
1704 swap_with_size (swapped, p, 2, mono_string_length (str));
1705 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1709 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1715 case MONO_TYPE_GENERICINST:
1716 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1719 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1722 /* there is no signature */
1723 mono_metadata_encode_value (len, b, &b);
1724 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1725 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1726 swap_with_size (blob_size, box_val, len, 1);
1727 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1729 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1737 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1742 sigbuffer_init (&buf, 32);
1744 sigbuffer_add_value (&buf, minfo->type);
1746 switch (minfo->type) {
1747 case MONO_NATIVE_BYVALTSTR:
1748 case MONO_NATIVE_BYVALARRAY:
1749 sigbuffer_add_value (&buf, minfo->count);
1751 case MONO_NATIVE_LPARRAY:
1752 if (minfo->eltype || minfo->has_size) {
1753 sigbuffer_add_value (&buf, minfo->eltype);
1754 if (minfo->has_size) {
1755 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1756 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1758 /* LAMESPEC: ElemMult is undocumented */
1759 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1763 case MONO_NATIVE_CUSTOM:
1765 str = mono_string_to_utf8 (minfo->guid);
1767 sigbuffer_add_value (&buf, len);
1768 sigbuffer_add_mem (&buf, str, len);
1771 sigbuffer_add_value (&buf, 0);
1773 /* native type name */
1774 sigbuffer_add_value (&buf, 0);
1775 /* custom marshaler type name */
1776 if (minfo->marshaltype || minfo->marshaltyperef) {
1777 if (minfo->marshaltyperef)
1778 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1780 str = mono_string_to_utf8 (minfo->marshaltype);
1782 sigbuffer_add_value (&buf, len);
1783 sigbuffer_add_mem (&buf, str, len);
1786 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1787 sigbuffer_add_value (&buf, 0);
1789 if (minfo->mcookie) {
1790 str = mono_string_to_utf8 (minfo->mcookie);
1792 sigbuffer_add_value (&buf, len);
1793 sigbuffer_add_mem (&buf, str, len);
1796 sigbuffer_add_value (&buf, 0);
1802 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1803 sigbuffer_free (&buf);
1808 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1810 MonoDynamicTable *table;
1813 /* maybe this fixup should be done in the C# code */
1814 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1815 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1816 table = &assembly->tables [MONO_TABLE_FIELD];
1817 fb->table_idx = table->next_idx ++;
1818 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1819 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1820 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1821 values [MONO_FIELD_FLAGS] = fb->attrs;
1822 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1824 if (fb->offset != -1) {
1825 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1827 alloc_table (table, table->rows);
1828 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1829 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1830 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1832 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1833 guint32 field_type = 0;
1834 table = &assembly->tables [MONO_TABLE_CONSTANT];
1836 alloc_table (table, table->rows);
1837 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1838 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1839 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1840 values [MONO_CONSTANT_TYPE] = field_type;
1841 values [MONO_CONSTANT_PADDING] = 0;
1843 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1845 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1847 alloc_table (table, table->rows);
1848 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1849 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1851 * We store it in the code section because it's simpler for now.
1854 if (mono_array_length (fb->rva_data) >= 10)
1855 stream_data_align (&assembly->code);
1856 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1858 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1859 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1861 if (fb->marshal_info) {
1862 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1864 alloc_table (table, table->rows);
1865 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1866 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1867 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1872 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1875 guint32 nparams = 0;
1876 MonoReflectionMethodBuilder *mb = fb->get_method;
1877 MonoReflectionMethodBuilder *smb = fb->set_method;
1880 if (mb && mb->parameters)
1881 nparams = mono_array_length (mb->parameters);
1882 if (!mb && smb && smb->parameters)
1883 nparams = mono_array_length (smb->parameters) - 1;
1884 sigbuffer_init (&buf, 32);
1885 sigbuffer_add_byte (&buf, 0x08);
1886 sigbuffer_add_value (&buf, nparams);
1888 encode_reflection_type (assembly, mb->rtype, &buf);
1889 for (i = 0; i < nparams; ++i) {
1890 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1891 encode_reflection_type (assembly, pt, &buf);
1893 } else if (smb && smb->parameters) {
1894 /* the property type is the last param */
1895 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1896 for (i = 0; i < nparams; ++i) {
1897 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1898 encode_reflection_type (assembly, pt, &buf);
1901 encode_reflection_type (assembly, fb->type, &buf);
1904 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1905 sigbuffer_free (&buf);
1910 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1912 MonoDynamicTable *table;
1914 guint num_methods = 0;
1918 * we need to set things in the following tables:
1919 * PROPERTYMAP (info already filled in _get_type_info ())
1920 * PROPERTY (rows already preallocated in _get_type_info ())
1921 * METHOD (method info already done with the generic method code)
1924 table = &assembly->tables [MONO_TABLE_PROPERTY];
1925 pb->table_idx = table->next_idx ++;
1926 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1927 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1928 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1929 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1931 /* FIXME: we still don't handle 'other' methods */
1932 if (pb->get_method) num_methods ++;
1933 if (pb->set_method) num_methods ++;
1935 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1936 table->rows += num_methods;
1937 alloc_table (table, table->rows);
1939 if (pb->get_method) {
1940 semaidx = table->next_idx ++;
1941 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1942 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1943 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1944 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1946 if (pb->set_method) {
1947 semaidx = table->next_idx ++;
1948 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1949 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1950 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1951 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1956 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1958 MonoDynamicTable *table;
1960 guint num_methods = 0;
1964 * we need to set things in the following tables:
1965 * EVENTMAP (info already filled in _get_type_info ())
1966 * EVENT (rows already preallocated in _get_type_info ())
1967 * METHOD (method info already done with the generic method code)
1970 table = &assembly->tables [MONO_TABLE_EVENT];
1971 eb->table_idx = table->next_idx ++;
1972 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1973 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1974 values [MONO_EVENT_FLAGS] = eb->attrs;
1975 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1978 * FIXME: we still don't handle 'other' methods
1980 if (eb->add_method) num_methods ++;
1981 if (eb->remove_method) num_methods ++;
1982 if (eb->raise_method) num_methods ++;
1984 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1985 table->rows += num_methods;
1986 alloc_table (table, table->rows);
1988 if (eb->add_method) {
1989 semaidx = table->next_idx ++;
1990 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1991 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1992 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1993 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1995 if (eb->remove_method) {
1996 semaidx = table->next_idx ++;
1997 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1998 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1999 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2000 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2002 if (eb->raise_method) {
2003 semaidx = table->next_idx ++;
2004 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2005 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2006 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2007 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2012 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2014 MonoDynamicTable *table;
2015 guint32 num_constraints, i;
2019 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2020 num_constraints = gparam->iface_constraints ?
2021 mono_array_length (gparam->iface_constraints) : 0;
2022 table->rows += num_constraints;
2023 if (gparam->base_type)
2025 alloc_table (table, table->rows);
2027 if (gparam->base_type) {
2028 table_idx = table->next_idx ++;
2029 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2031 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2032 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2033 assembly, gparam->base_type->type);
2036 for (i = 0; i < num_constraints; i++) {
2037 MonoReflectionType *constraint = mono_array_get (
2038 gparam->iface_constraints, gpointer, i);
2040 table_idx = table->next_idx ++;
2041 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2043 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2044 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2045 assembly, constraint->type);
2050 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2052 GenericParamTableEntry *entry;
2055 * The GenericParam table must be sorted according to the `owner' field.
2056 * We need to do this sorting prior to writing the GenericParamConstraint
2057 * table, since we have to use the final GenericParam table indices there
2058 * and they must also be sorted.
2061 entry = g_new0 (GenericParamTableEntry, 1);
2062 entry->owner = owner;
2064 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2065 MONO_GC_REGISTER_ROOT (entry->gparam);
2067 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2069 g_ptr_array_add (assembly->gen_params, entry);
2073 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2075 MonoDynamicTable *table;
2076 MonoGenericParam *param;
2080 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2081 table_idx = table->next_idx ++;
2082 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2084 param = entry->gparam->type.type->data.generic_param;
2086 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2087 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2088 values [MONO_GENERICPARAM_NUMBER] = param->num;
2089 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2091 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2093 encode_constraints (entry->gparam, table_idx, assembly);
2097 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2099 MonoDynamicTable *table;
2102 guint32 cols [MONO_ASSEMBLY_SIZE];
2106 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2109 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2110 table = &assembly->tables [MONO_TABLE_MODULEREF];
2111 token = table->next_idx ++;
2113 alloc_table (table, table->rows);
2114 values = table->values + token * MONO_MODULEREF_SIZE;
2115 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2117 token <<= MONO_RESOLTION_SCOPE_BITS;
2118 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2119 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2124 if (image->assembly->dynamic)
2126 memset (cols, 0, sizeof (cols));
2128 /* image->assembly->image is the manifest module */
2129 image = image->assembly->image;
2130 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2133 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2134 token = table->next_idx ++;
2136 alloc_table (table, table->rows);
2137 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2138 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2139 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2140 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2141 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2142 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2143 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2144 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2145 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2147 if (strcmp ("", image->assembly->aname.culture)) {
2148 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2149 image->assembly->aname.culture);
2152 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2153 guchar pubtoken [9];
2155 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2156 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2158 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2160 token <<= MONO_RESOLTION_SCOPE_BITS;
2161 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2162 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2167 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2169 MonoDynamicTable *table;
2174 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2177 sigbuffer_init (&buf, 32);
2178 switch (type->type) {
2179 case MONO_TYPE_FNPTR:
2181 case MONO_TYPE_SZARRAY:
2182 case MONO_TYPE_ARRAY:
2184 case MONO_TYPE_MVAR:
2185 case MONO_TYPE_GENERICINST:
2186 encode_type (assembly, type, &buf);
2188 case MONO_TYPE_CLASS:
2189 case MONO_TYPE_VALUETYPE: {
2190 MonoClass *k = mono_class_from_mono_type (type);
2191 if (!k || !k->generic_container) {
2192 sigbuffer_free (&buf);
2195 encode_type (assembly, type, &buf);
2199 sigbuffer_free (&buf);
2203 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2204 if (assembly->save) {
2205 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2206 alloc_table (table, table->rows + 1);
2207 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2208 values [MONO_TYPESPEC_SIGNATURE] = token;
2210 sigbuffer_free (&buf);
2212 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2213 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2219 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2221 MonoDynamicTable *table;
2223 guint32 token, scope, enclosing;
2226 /* if the type requires a typespec, we must try that first*/
2227 if (try_typespec && (token = create_typespec (assembly, type)))
2229 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2232 klass = my_mono_class_from_mono_type (type);
2234 klass = mono_class_from_mono_type (type);
2237 * If it's in the same module and not a generic type parameter:
2239 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2240 (type->type != MONO_TYPE_MVAR)) {
2241 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2242 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2243 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2247 if (klass->nested_in) {
2248 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2249 /* get the typeref idx of the enclosing type */
2250 enclosing >>= MONO_TYPEDEFORREF_BITS;
2251 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2253 scope = resolution_scope_from_image (assembly, klass->image);
2255 table = &assembly->tables [MONO_TABLE_TYPEREF];
2256 if (assembly->save) {
2257 alloc_table (table, table->rows + 1);
2258 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2259 values [MONO_TYPEREF_SCOPE] = scope;
2260 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2261 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2263 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2264 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2266 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2271 * Despite the name, we handle also TypeSpec (with the above helper).
2274 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2276 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2280 * Insert a memberef row into the metadata: the token that point to the memberref
2281 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2282 * mono_image_get_fieldref_token()).
2283 * The sig param is an index to an already built signature.
2286 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2288 MonoDynamicTable *table;
2290 guint32 token, pclass;
2293 parent = mono_image_typedef_or_ref (assembly, type);
2294 switch (parent & MONO_TYPEDEFORREF_MASK) {
2295 case MONO_TYPEDEFORREF_TYPEREF:
2296 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2298 case MONO_TYPEDEFORREF_TYPESPEC:
2299 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2301 case MONO_TYPEDEFORREF_TYPEDEF:
2302 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2305 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2308 /* extract the index */
2309 parent >>= MONO_TYPEDEFORREF_BITS;
2311 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2313 if (assembly->save) {
2314 alloc_table (table, table->rows + 1);
2315 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2316 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2317 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2318 values [MONO_MEMBERREF_SIGNATURE] = sig;
2321 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2328 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2331 MonoMethodSignature *sig;
2333 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2338 * A methodref signature can't contain an unmanaged calling convention.
2340 sig = mono_metadata_signature_dup (mono_method_signature (method));
2341 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2342 sig->call_convention = MONO_CALL_DEFAULT;
2343 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2344 method->name, method_encode_signature (assembly, sig));
2346 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2351 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2354 ReflectionMethodBuilder rmb;
2357 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2361 name = mono_string_to_utf8 (method->name);
2362 reflection_methodbuilder_from_method_builder (&rmb, method);
2365 * A methodref signature can't contain an unmanaged calling convention.
2366 * Since some flags are encoded as part of call_conv, we need to check against it.
2368 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2369 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2370 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2371 name, method_builder_encode_signature (assembly, &rmb));
2374 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2379 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2380 const gchar *name, guint32 sig)
2382 MonoDynamicTable *table;
2386 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2388 if (assembly->save) {
2389 alloc_table (table, table->rows + 1);
2390 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2391 values [MONO_MEMBERREF_CLASS] = original;
2392 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2393 values [MONO_MEMBERREF_SIGNATURE] = sig;
2396 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2403 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2407 guint32 nparams = mono_array_length (mb->generic_params);
2410 if (!assembly->save)
2413 sigbuffer_init (&buf, 32);
2415 sigbuffer_add_value (&buf, 0xa);
2416 sigbuffer_add_value (&buf, nparams);
2418 for (i = 0; i < nparams; i++) {
2419 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2420 sigbuffer_add_value (&buf, i);
2423 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2424 sigbuffer_free (&buf);
2429 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2431 MonoDynamicTable *table;
2433 guint32 token, mtoken = 0;
2435 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2439 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2441 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2442 switch (mono_metadata_token_table (mtoken)) {
2443 case MONO_TABLE_MEMBERREF:
2444 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2446 case MONO_TABLE_METHOD:
2447 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2450 g_assert_not_reached ();
2453 if (assembly->save) {
2454 alloc_table (table, table->rows + 1);
2455 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2456 values [MONO_METHODSPEC_METHOD] = mtoken;
2457 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2460 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2463 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2468 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2472 if (mb->generic_params && create_methodspec)
2473 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2475 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2479 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2480 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2485 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2488 ReflectionMethodBuilder rmb;
2491 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2495 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2497 name = mono_string_to_utf8 (rmb.name);
2498 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2499 name, method_builder_encode_signature (assembly, &rmb));
2502 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2507 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2512 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2515 g_assert (f->field->parent);
2516 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2517 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2518 f->field->name, fieldref_encode_signature (assembly, type));
2519 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2524 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2528 MonoGenericClass *gclass;
2529 MonoDynamicGenericClass *dgclass;
2530 MonoReflectionFieldBuilder *fb = f->fb;
2533 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2536 klass = mono_class_from_mono_type (f->inst->type.type);
2537 gclass = f->inst->type.type->data.generic_class;
2538 g_assert (gclass->is_dynamic);
2539 dgclass = (MonoDynamicGenericClass *) gclass;
2541 name = mono_string_to_utf8 (fb->name);
2542 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2543 fieldref_encode_signature (assembly, fb->type->type));
2545 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2550 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2554 MonoGenericClass *gclass;
2555 MonoDynamicGenericClass *dgclass;
2556 MonoReflectionCtorBuilder *cb = c->cb;
2557 ReflectionMethodBuilder rmb;
2560 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2562 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2565 klass = mono_class_from_mono_type (c->inst->type.type);
2566 gclass = c->inst->type.type->data.generic_class;
2567 g_assert (gclass->is_dynamic);
2568 dgclass = (MonoDynamicGenericClass *) gclass;
2570 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2572 name = mono_string_to_utf8 (rmb.name);
2574 sig = method_builder_encode_signature (assembly, &rmb);
2576 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2579 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2584 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2588 MonoGenericClass *gclass;
2589 MonoReflectionMethodBuilder *mb = m->mb;
2590 ReflectionMethodBuilder rmb;
2593 if (create_methodspec && mb->generic_params)
2595 g_assert_not_reached ();
2597 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2600 klass = mono_class_from_mono_type (m->inst->type.type);
2601 gclass = m->inst->type.type->data.generic_class;
2602 g_assert (gclass->is_dynamic);
2604 reflection_methodbuilder_from_method_builder (&rmb, mb);
2606 name = mono_string_to_utf8 (rmb.name);
2608 sig = method_builder_encode_signature (assembly, &rmb);
2610 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2613 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2618 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2622 guint32 nparams = context->method_inst->type_argc;
2625 if (!assembly->save)
2628 sigbuffer_init (&buf, 32);
2630 * FIXME: vararg, explicit_this, differenc call_conv values...
2632 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2633 sigbuffer_add_value (&buf, nparams);
2635 for (i = 0; i < nparams; i++)
2636 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2638 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2639 sigbuffer_free (&buf);
2644 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2646 MonoDynamicTable *table;
2648 guint32 token, mtoken = 0, sig;
2649 MonoMethodInflated *imethod;
2650 MonoMethod *declaring;
2652 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2654 g_assert (method->is_inflated);
2655 imethod = (MonoMethodInflated *) method;
2656 declaring = imethod->declaring;
2658 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2659 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2661 if (!mono_method_signature (declaring)->generic_param_count)
2664 switch (mono_metadata_token_table (mtoken)) {
2665 case MONO_TABLE_MEMBERREF:
2666 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2668 case MONO_TABLE_METHOD:
2669 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2672 g_assert_not_reached ();
2675 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2677 if (assembly->save) {
2678 alloc_table (table, table->rows + 1);
2679 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2680 values [MONO_METHODSPEC_METHOD] = mtoken;
2681 values [MONO_METHODSPEC_SIGNATURE] = sig;
2684 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2691 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2693 MonoMethodInflated *imethod;
2696 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2700 g_assert (method->is_inflated);
2701 imethod = (MonoMethodInflated *) method;
2703 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2704 token = method_encode_methodspec (assembly, method);
2706 guint32 sig = method_encode_signature (
2707 assembly, mono_method_signature (imethod->declaring));
2708 token = mono_image_get_memberref_token (
2709 assembly, &method->klass->byval_arg, method->name, sig);
2712 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2717 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2719 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2722 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2723 token = mono_image_get_memberref_token (
2724 assembly, &m->klass->byval_arg, m->name, sig);
2730 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2732 MonoDynamicTable *table;
2740 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2741 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2742 * Because of this, we must not insert it into the `typeref' hash table.
2745 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2749 sigbuffer_init (&buf, 32);
2751 g_assert (tb->generic_params);
2752 klass = mono_class_from_mono_type (tb->type.type);
2754 if (tb->generic_container)
2755 mono_reflection_create_generic_class (tb);
2757 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2758 g_assert (klass->generic_container);
2759 sigbuffer_add_value (&buf, klass->byval_arg.type);
2760 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2762 count = mono_array_length (tb->generic_params);
2763 sigbuffer_add_value (&buf, count);
2764 for (i = 0; i < count; i++) {
2765 MonoReflectionGenericParam *gparam;
2767 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2769 encode_type (assembly, gparam->type.type, &buf);
2772 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2774 if (assembly->save) {
2775 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2776 alloc_table (table, table->rows + 1);
2777 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2778 values [MONO_TYPESPEC_SIGNATURE] = token;
2780 sigbuffer_free (&buf);
2782 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2783 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2789 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2791 MonoDynamicTable *table;
2794 guint32 token, pclass, parent, sig;
2797 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2801 klass = mono_class_from_mono_type (fb->typeb->type);
2802 name = mono_string_to_utf8 (fb->name);
2804 sig = fieldref_encode_signature (assembly, fb->type->type);
2806 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2807 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2809 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2810 parent >>= MONO_TYPEDEFORREF_BITS;
2812 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2814 if (assembly->save) {
2815 alloc_table (table, table->rows + 1);
2816 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2817 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2818 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2819 values [MONO_MEMBERREF_SIGNATURE] = sig;
2822 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2824 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2830 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2837 if (!assembly->save)
2840 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2841 g_assert (helper->type == 2);
2843 if (helper->arguments)
2844 nargs = mono_array_length (helper->arguments);
2848 size = 10 + (nargs * 10);
2850 sigbuffer_init (&buf, 32);
2852 /* Encode calling convention */
2853 /* Change Any to Standard */
2854 if ((helper->call_conv & 0x03) == 0x03)
2855 helper->call_conv = 0x01;
2856 /* explicit_this implies has_this */
2857 if (helper->call_conv & 0x40)
2858 helper->call_conv &= 0x20;
2860 if (helper->call_conv == 0) { /* Unmanaged */
2861 idx = helper->unmanaged_call_conv - 1;
2864 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2865 if (helper->call_conv & 0x02) /* varargs */
2869 sigbuffer_add_byte (&buf, idx);
2870 sigbuffer_add_value (&buf, nargs);
2871 encode_reflection_type (assembly, helper->return_type, &buf);
2872 for (i = 0; i < nargs; ++i) {
2873 MonoArray *modreqs = NULL;
2874 MonoArray *modopts = NULL;
2875 MonoReflectionType *pt;
2877 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
2878 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
2879 if (helper->modopts && (i < mono_array_length (helper->modopts)))
2880 modopts = mono_array_get (helper->modopts, MonoArray*, i);
2882 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
2883 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2884 encode_reflection_type (assembly, pt, &buf);
2886 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2887 sigbuffer_free (&buf);
2893 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2896 MonoDynamicTable *table;
2899 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2900 idx = table->next_idx ++;
2902 alloc_table (table, table->rows);
2903 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2905 values [MONO_STAND_ALONE_SIGNATURE] =
2906 mono_reflection_encode_sighelper (assembly, helper);
2912 reflection_cc_to_file (int call_conv) {
2913 switch (call_conv & 0x3) {
2915 case 1: return MONO_CALL_DEFAULT;
2916 case 2: return MONO_CALL_VARARG;
2918 g_assert_not_reached ();
2925 MonoMethodSignature *sig;
2931 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2936 MonoMethodSignature *sig;
2939 name = mono_string_to_utf8 (m->name);
2940 nparams = mono_array_length (m->parameters);
2941 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2943 sig->sentinelpos = -1;
2944 sig->call_convention = reflection_cc_to_file (m->call_conv);
2945 sig->param_count = nparams;
2946 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2947 for (i = 0; i < nparams; ++i) {
2948 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2949 sig->params [i] = t->type;
2952 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2954 if (strcmp (name, am->name) == 0 &&
2955 mono_metadata_type_equal (am->parent, m->parent->type) &&
2956 mono_metadata_signature_equal (am->sig, sig)) {
2959 m->table_idx = am->token & 0xffffff;
2963 am = g_new0 (ArrayMethod, 1);
2966 am->parent = m->parent->type;
2967 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2968 method_encode_signature (assembly, sig));
2969 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2970 m->table_idx = am->token & 0xffffff;
2975 * Insert into the metadata tables all the info about the TypeBuilder tb.
2976 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2979 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2981 MonoDynamicTable *table;
2983 int i, is_object = 0, is_system = 0;
2986 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2987 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2988 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2989 n = mono_string_to_utf8 (tb->name);
2990 if (strcmp (n, "Object") == 0)
2992 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2994 n = mono_string_to_utf8 (tb->nspace);
2995 if (strcmp (n, "System") == 0)
2997 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2999 if (tb->parent && !(is_system && is_object) &&
3000 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3001 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
3003 values [MONO_TYPEDEF_EXTENDS] = 0;
3005 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3006 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3009 * if we have explicitlayout or sequentiallayouts, output data in the
3010 * ClassLayout table.
3012 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3013 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3014 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3016 alloc_table (table, table->rows);
3017 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3018 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3019 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3020 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3023 /* handle interfaces */
3024 if (tb->interfaces) {
3025 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3027 table->rows += mono_array_length (tb->interfaces);
3028 alloc_table (table, table->rows);
3029 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3030 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3031 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3032 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3033 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3034 values += MONO_INTERFACEIMPL_SIZE;
3040 table = &assembly->tables [MONO_TABLE_FIELD];
3041 table->rows += tb->num_fields;
3042 alloc_table (table, table->rows);
3043 for (i = 0; i < tb->num_fields; ++i)
3044 mono_image_get_field_info (
3045 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3048 /* handle constructors */
3050 table = &assembly->tables [MONO_TABLE_METHOD];
3051 table->rows += mono_array_length (tb->ctors);
3052 alloc_table (table, table->rows);
3053 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3054 mono_image_get_ctor_info (domain,
3055 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3058 /* handle methods */
3060 table = &assembly->tables [MONO_TABLE_METHOD];
3061 table->rows += tb->num_methods;
3062 alloc_table (table, table->rows);
3063 for (i = 0; i < tb->num_methods; ++i)
3064 mono_image_get_method_info (
3065 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3068 /* Do the same with properties etc.. */
3069 if (tb->events && mono_array_length (tb->events)) {
3070 table = &assembly->tables [MONO_TABLE_EVENT];
3071 table->rows += mono_array_length (tb->events);
3072 alloc_table (table, table->rows);
3073 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3075 alloc_table (table, table->rows);
3076 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3077 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3078 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3079 for (i = 0; i < mono_array_length (tb->events); ++i)
3080 mono_image_get_event_info (
3081 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3083 if (tb->properties && mono_array_length (tb->properties)) {
3084 table = &assembly->tables [MONO_TABLE_PROPERTY];
3085 table->rows += mono_array_length (tb->properties);
3086 alloc_table (table, table->rows);
3087 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3089 alloc_table (table, table->rows);
3090 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3091 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3092 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3093 for (i = 0; i < mono_array_length (tb->properties); ++i)
3094 mono_image_get_property_info (
3095 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3098 /* handle generic parameters */
3099 if (tb->generic_params) {
3100 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3101 table->rows += mono_array_length (tb->generic_params);
3102 alloc_table (table, table->rows);
3103 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3104 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3106 mono_image_get_generic_param_info (
3107 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3111 mono_image_add_decl_security (assembly,
3112 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3115 MonoDynamicTable *ntable;
3117 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3118 ntable->rows += mono_array_length (tb->subtypes);
3119 alloc_table (ntable, ntable->rows);
3120 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3122 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3123 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3125 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3126 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3127 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3128 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3129 mono_string_to_utf8 (tb->name), tb->table_idx,
3130 ntable->next_idx, ntable->rows);*/
3131 values += MONO_NESTED_CLASS_SIZE;
3138 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3142 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3144 if (!type->subtypes)
3147 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3148 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3149 collect_types (types, subtype);
3154 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3156 if ((*type1)->table_idx < (*type2)->table_idx)
3159 if ((*type1)->table_idx > (*type2)->table_idx)
3166 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3171 for (i = 0; i < mono_array_length (pinfo); ++i) {
3172 MonoReflectionParamBuilder *pb;
3173 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3176 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3181 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3184 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3186 for (i = 0; i < tb->num_fields; ++i) {
3187 MonoReflectionFieldBuilder* fb;
3188 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3189 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3193 for (i = 0; i < mono_array_length (tb->events); ++i) {
3194 MonoReflectionEventBuilder* eb;
3195 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3196 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3199 if (tb->properties) {
3200 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3201 MonoReflectionPropertyBuilder* pb;
3202 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3203 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3207 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3208 MonoReflectionCtorBuilder* cb;
3209 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3210 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3211 params_add_cattrs (assembly, cb->pinfo);
3216 for (i = 0; i < tb->num_methods; ++i) {
3217 MonoReflectionMethodBuilder* mb;
3218 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3219 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3220 params_add_cattrs (assembly, mb->pinfo);
3225 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3226 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3231 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3235 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3237 if (moduleb->global_methods) {
3238 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3239 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3240 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3241 params_add_cattrs (assembly, mb->pinfo);
3245 if (moduleb->global_fields) {
3246 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3247 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3248 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3252 if (moduleb->types) {
3253 for (i = 0; i < moduleb->num_types; ++i)
3254 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3259 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3261 MonoDynamicTable *table;
3265 char *b = blob_size;
3268 table = &assembly->tables [MONO_TABLE_FILE];
3270 alloc_table (table, table->rows);
3271 values = table->values + table->next_idx * MONO_FILE_SIZE;
3272 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3273 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3274 if (module->image->dynamic) {
3275 /* This depends on the fact that the main module is emitted last */
3276 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3277 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3280 path = g_strdup (module->image->name);
3282 mono_sha1_get_digest_from_file (path, hash);
3285 mono_metadata_encode_value (20, b, &b);
3286 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3287 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3292 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3294 MonoDynamicTable *table;
3297 table = &assembly->tables [MONO_TABLE_MODULE];
3298 mb->table_idx = table->next_idx ++;
3299 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3300 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3303 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3304 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3305 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3306 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3310 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3311 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3313 MonoDynamicTable *table;
3317 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3318 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3321 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3323 alloc_table (table, table->rows);
3324 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3326 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3327 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3328 if (klass->nested_in)
3329 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3331 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3332 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3333 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3335 res = table->next_idx;
3339 /* Emit nested types */
3340 if (klass->nested_classes) {
3343 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3344 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3351 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3352 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3357 klass = mono_class_from_mono_type (tb->type.type);
3359 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3361 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3362 parent_index, assembly);
3366 * We need to do this ourselves since klass->nested_classes is not set up.
3369 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3370 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3375 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3376 guint32 module_index, MonoDynamicImage *assembly)
3378 MonoImage *image = module->image;
3382 t = &image->tables [MONO_TABLE_TYPEDEF];
3384 for (i = 0; i < t->rows; ++i) {
3385 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3387 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3388 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3393 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3395 MonoDynamicTable *table;
3401 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3403 if (assemblyb->type_forwarders) {
3404 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3405 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3411 klass = mono_class_from_mono_type (t->type);
3413 scope = resolution_scope_from_image (assembly, klass->image);
3414 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3415 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3418 alloc_table (table, table->rows);
3419 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3421 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3422 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3423 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3424 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3425 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3430 #define align_pointer(base,p)\
3432 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3434 (p) += 4 - (__diff & 3);\
3438 compare_constants (const void *a, const void *b)
3440 const guint32 *a_values = a;
3441 const guint32 *b_values = b;
3442 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3446 compare_semantics (const void *a, const void *b)
3448 const guint32 *a_values = a;
3449 const guint32 *b_values = b;
3450 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3453 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3457 compare_custom_attrs (const void *a, const void *b)
3459 const guint32 *a_values = a;
3460 const guint32 *b_values = b;
3462 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3466 compare_field_marshal (const void *a, const void *b)
3468 const guint32 *a_values = a;
3469 const guint32 *b_values = b;
3471 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3475 compare_nested (const void *a, const void *b)
3477 const guint32 *a_values = a;
3478 const guint32 *b_values = b;
3480 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3484 compare_genericparam (const void *a, const void *b)
3486 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3487 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3489 if ((*b_entry)->owner == (*a_entry)->owner)
3491 (*a_entry)->gparam->type.type->data.generic_param->num -
3492 (*b_entry)->gparam->type.type->data.generic_param->num;
3494 return (*a_entry)->owner - (*b_entry)->owner;
3498 compare_declsecurity_attrs (const void *a, const void *b)
3500 const guint32 *a_values = a;
3501 const guint32 *b_values = b;
3503 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3507 pad_heap (MonoDynamicStream *sh)
3509 if (sh->index & 3) {
3510 int sz = 4 - (sh->index & 3);
3511 memset (sh->data + sh->index, 0, sz);
3518 MonoDynamicStream *stream;
3522 * build_compressed_metadata() fills in the blob of data that represents the
3523 * raw metadata as it will be saved in the PE file. The five streams are output
3524 * and the metadata tables are comnpressed from the guint32 array representation,
3525 * to the compressed on-disk format.
3528 build_compressed_metadata (MonoDynamicImage *assembly)
3530 MonoDynamicTable *table;
3532 guint64 valid_mask = 0;
3533 guint64 sorted_mask;
3534 guint32 heapt_size = 0;
3535 guint32 meta_size = 256; /* allow for header and other stuff */
3536 guint32 table_offset;
3537 guint32 ntables = 0;
3543 struct StreamDesc stream_desc [5];
3545 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3546 for (i = 0; i < assembly->gen_params->len; i++){
3547 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3548 write_generic_param_entry (assembly, entry);
3551 stream_desc [0].name = "#~";
3552 stream_desc [0].stream = &assembly->tstream;
3553 stream_desc [1].name = "#Strings";
3554 stream_desc [1].stream = &assembly->sheap;
3555 stream_desc [2].name = "#US";
3556 stream_desc [2].stream = &assembly->us;
3557 stream_desc [3].name = "#Blob";
3558 stream_desc [3].stream = &assembly->blob;
3559 stream_desc [4].name = "#GUID";
3560 stream_desc [4].stream = &assembly->guid;
3562 /* tables that are sorted */
3563 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3564 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3565 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3566 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3567 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3568 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3570 /* Compute table sizes */
3571 /* the MonoImage has already been created in mono_image_basic_init() */
3572 meta = &assembly->image;
3574 /* sizes should be multiple of 4 */
3575 pad_heap (&assembly->blob);
3576 pad_heap (&assembly->guid);
3577 pad_heap (&assembly->sheap);
3578 pad_heap (&assembly->us);
3580 /* Setup the info used by compute_sizes () */
3581 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3582 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3583 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3585 meta_size += assembly->blob.index;
3586 meta_size += assembly->guid.index;
3587 meta_size += assembly->sheap.index;
3588 meta_size += assembly->us.index;
3590 for (i=0; i < MONO_TABLE_NUM; ++i)
3591 meta->tables [i].rows = assembly->tables [i].rows;
3593 for (i = 0; i < MONO_TABLE_NUM; i++){
3594 if (meta->tables [i].rows == 0)
3596 valid_mask |= (guint64)1 << i;
3598 meta->tables [i].row_size = mono_metadata_compute_size (
3599 meta, i, &meta->tables [i].size_bitfield);
3600 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3602 heapt_size += 24; /* #~ header size */
3603 heapt_size += ntables * 4;
3604 /* make multiple of 4 */
3607 meta_size += heapt_size;
3608 meta->raw_metadata = g_malloc0 (meta_size);
3609 p = (unsigned char*)meta->raw_metadata;
3610 /* the metadata signature */
3611 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3612 /* version numbers and 4 bytes reserved */
3613 int16val = (guint16*)p;
3614 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3615 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3617 /* version string */
3618 int32val = (guint32*)p;
3619 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3621 memcpy (p, meta->version, strlen (meta->version));
3622 p += GUINT32_FROM_LE (*int32val);
3623 align_pointer (meta->raw_metadata, p);
3624 int16val = (guint16*)p;
3625 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3626 *int16val = GUINT16_TO_LE (5); /* number of streams */
3630 * write the stream info.
3632 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3633 table_offset += 3; table_offset &= ~3;
3635 assembly->tstream.index = heapt_size;
3636 for (i = 0; i < 5; ++i) {
3637 int32val = (guint32*)p;
3638 stream_desc [i].stream->offset = table_offset;
3639 *int32val++ = GUINT32_TO_LE (table_offset);
3640 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3641 table_offset += GUINT32_FROM_LE (*int32val);
3642 table_offset += 3; table_offset &= ~3;
3644 strcpy ((char*)p, stream_desc [i].name);
3645 p += strlen (stream_desc [i].name) + 1;
3646 align_pointer (meta->raw_metadata, p);
3649 * now copy the data, the table stream header and contents goes first.
3651 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3652 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3653 int32val = (guint32*)p;
3654 *int32val = GUINT32_TO_LE (0); /* reserved */
3657 if (mono_get_runtime_info ()->framework_version [0] > '1') {
3658 *p++ = 2; /* version */
3661 *p++ = 1; /* version */
3665 if (meta->idx_string_wide)
3667 if (meta->idx_guid_wide)
3669 if (meta->idx_blob_wide)
3672 *p++ = 1; /* reserved */
3673 int64val = (guint64*)p;
3674 *int64val++ = GUINT64_TO_LE (valid_mask);
3675 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3677 int32val = (guint32*)p;
3678 for (i = 0; i < MONO_TABLE_NUM; i++){
3679 if (meta->tables [i].rows == 0)
3681 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3683 p = (unsigned char*)int32val;
3685 /* sort the tables that still need sorting */
3686 table = &assembly->tables [MONO_TABLE_CONSTANT];
3688 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3689 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3691 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3692 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3694 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3695 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3697 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3698 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3700 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3701 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3702 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3704 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3706 /* compress the tables */
3707 for (i = 0; i < MONO_TABLE_NUM; i++){
3710 guint32 bitfield = meta->tables [i].size_bitfield;
3711 if (!meta->tables [i].rows)
3713 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3714 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3715 meta->tables [i].base = (char*)p;
3716 for (row = 1; row <= meta->tables [i].rows; ++row) {
3717 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3718 for (col = 0; col < assembly->tables [i].columns; ++col) {
3719 switch (mono_metadata_table_size (bitfield, col)) {
3721 *p++ = values [col];
3724 *p++ = values [col] & 0xff;
3725 *p++ = (values [col] >> 8) & 0xff;
3728 *p++ = values [col] & 0xff;
3729 *p++ = (values [col] >> 8) & 0xff;
3730 *p++ = (values [col] >> 16) & 0xff;
3731 *p++ = (values [col] >> 24) & 0xff;
3734 g_assert_not_reached ();
3738 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3741 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3742 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3743 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3744 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3745 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3747 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3751 * Some tables in metadata need to be sorted according to some criteria, but
3752 * when methods and fields are first created with reflection, they may be assigned a token
3753 * that doesn't correspond to the final token they will get assigned after the sorting.
3754 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3755 * with the reflection objects that represent them. Once all the tables are set up, the
3756 * reflection objects will contains the correct table index. fixup_method() will fixup the
3757 * tokens for the method with ILGenerator @ilgen.
3760 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3762 guint32 code_idx = GPOINTER_TO_UINT (value);
3763 MonoReflectionILTokenInfo *iltoken;
3764 MonoReflectionFieldBuilder *field;
3765 MonoReflectionCtorBuilder *ctor;
3766 MonoReflectionMethodBuilder *method;
3767 MonoReflectionTypeBuilder *tb;
3768 MonoReflectionArrayMethod *am;
3770 unsigned char *target;
3772 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3773 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3774 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3775 switch (target [3]) {
3776 case MONO_TABLE_FIELD:
3777 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3778 field = (MonoReflectionFieldBuilder *)iltoken->member;
3779 idx = field->table_idx;
3780 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3781 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3782 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3784 g_assert_not_reached ();
3787 case MONO_TABLE_METHOD:
3788 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3789 method = (MonoReflectionMethodBuilder *)iltoken->member;
3790 idx = method->table_idx;
3791 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3792 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3793 idx = ctor->table_idx;
3794 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3795 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3796 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3797 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3799 g_assert_not_reached ();
3802 case MONO_TABLE_TYPEDEF:
3803 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3804 g_assert_not_reached ();
3805 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3806 idx = tb->table_idx;
3808 case MONO_TABLE_MEMBERREF:
3809 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3810 am = (MonoReflectionArrayMethod*)iltoken->member;
3811 idx = am->table_idx;
3812 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3813 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3814 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3815 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3816 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3817 g_assert (m->klass->generic_class || m->klass->generic_container);
3819 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3821 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3822 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3823 g_assert (f->generic_info);
3825 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3826 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3828 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3830 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
3832 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
3835 g_assert_not_reached ();
3838 case MONO_TABLE_METHODSPEC:
3839 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3840 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3841 g_assert (mono_method_signature (m)->generic_param_count);
3843 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3846 g_assert_not_reached ();
3850 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3852 target [0] = idx & 0xff;
3853 target [1] = (idx >> 8) & 0xff;
3854 target [2] = (idx >> 16) & 0xff;
3861 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3862 * value is not known when the table is emitted.
3865 fixup_cattrs (MonoDynamicImage *assembly)
3867 MonoDynamicTable *table;
3869 guint32 type, i, idx, token;
3872 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3874 for (i = 0; i < table->rows; ++i) {
3875 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3877 type = values [MONO_CUSTOM_ATTR_TYPE];
3878 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3879 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3880 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3881 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3884 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3885 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3886 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3887 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3894 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3896 MonoDynamicTable *table;
3899 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3901 alloc_table (table, table->rows);
3902 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3903 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3904 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3905 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3906 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3911 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3913 MonoDynamicTable *table;
3917 char *b = blob_size;
3919 guint32 idx, offset;
3921 if (rsrc->filename) {
3922 name = mono_string_to_utf8 (rsrc->filename);
3923 sname = g_path_get_basename (name);
3925 table = &assembly->tables [MONO_TABLE_FILE];
3927 alloc_table (table, table->rows);
3928 values = table->values + table->next_idx * MONO_FILE_SIZE;
3929 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3930 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3933 mono_sha1_get_digest_from_file (name, hash);
3934 mono_metadata_encode_value (20, b, &b);
3935 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3936 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3938 idx = table->next_idx++;
3940 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3946 data = mono_array_addr (rsrc->data, char, 0);
3947 len = mono_array_length (rsrc->data);
3953 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3954 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3955 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3956 mono_image_add_stream_data (&assembly->resources, data, len);
3960 * The entry should be emitted into the MANIFESTRESOURCE table of
3961 * the main module, but that needs to reference the FILE table
3962 * which isn't emitted yet.
3969 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3973 set_version_from_string (MonoString *version, guint32 *values)
3975 gchar *ver, *p, *str;
3978 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3979 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3980 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3981 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3984 ver = str = mono_string_to_utf8 (version);
3985 for (i = 0; i < 4; ++i) {
3986 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3992 /* handle Revision and Build */
4002 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4006 char *b = blob_size;
4011 len = mono_array_length (pkey);
4012 mono_metadata_encode_value (len, b, &b);
4013 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4014 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4016 assembly->public_key = g_malloc (len);
4017 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4018 assembly->public_key_len = len;
4020 /* Special case: check for ECMA key (16 bytes) */
4021 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4022 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4023 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4024 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4025 /* minimum key size (in 2.0) is 384 bits */
4026 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4028 /* FIXME - verifier */
4029 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4030 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4032 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4038 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4040 MonoDynamicTable *table;
4041 MonoDynamicImage *assembly;
4042 MonoReflectionAssemblyBuilder *assemblyb;
4046 guint32 module_index;
4048 assemblyb = moduleb->assemblyb;
4049 assembly = moduleb->dynamic_image;
4050 domain = mono_object_domain (assemblyb);
4052 /* Emit ASSEMBLY table */
4053 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4054 alloc_table (table, 1);
4055 values = table->values + MONO_ASSEMBLY_SIZE;
4056 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4057 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4058 if (assemblyb->culture) {
4059 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4061 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4063 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4064 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4065 set_version_from_string (assemblyb->version, values);
4067 /* Emit FILE + EXPORTED_TYPE table */
4069 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4071 MonoReflectionModuleBuilder *file_module =
4072 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4073 if (file_module != moduleb) {
4074 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4076 if (file_module->types) {
4077 for (j = 0; j < file_module->num_types; ++j) {
4078 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4079 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4084 if (assemblyb->loaded_modules) {
4085 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4086 MonoReflectionModule *file_module =
4087 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4088 mono_image_fill_file_table (domain, file_module, assembly);
4090 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4093 if (assemblyb->type_forwarders)
4094 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4096 /* Emit MANIFESTRESOURCE table */
4098 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4100 MonoReflectionModuleBuilder *file_module =
4101 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4102 /* The table for the main module is emitted later */
4103 if (file_module != moduleb) {
4105 if (file_module->resources) {
4106 int len = mono_array_length (file_module->resources);
4107 for (j = 0; j < len; ++j) {
4108 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4109 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4117 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4118 * for the modulebuilder @moduleb.
4119 * At the end of the process, method and field tokens are fixed up and the
4120 * on-disk compressed metadata representation is created.
4123 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4125 MonoDynamicTable *table;
4126 MonoDynamicImage *assembly;
4127 MonoReflectionAssemblyBuilder *assemblyb;
4133 assemblyb = moduleb->assemblyb;
4134 assembly = moduleb->dynamic_image;
4135 domain = mono_object_domain (assemblyb);
4137 if (assembly->text_rva)
4140 assembly->text_rva = START_TEXT_RVA;
4142 if (moduleb->is_main) {
4143 mono_image_emit_manifest (moduleb);
4146 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4147 table->rows = 1; /* .<Module> */
4149 alloc_table (table, table->rows);
4151 * Set the first entry.
4153 values = table->values + table->columns;
4154 values [MONO_TYPEDEF_FLAGS] = 0;
4155 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4156 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4157 values [MONO_TYPEDEF_EXTENDS] = 0;
4158 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4159 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4162 * handle global methods
4163 * FIXME: test what to do when global methods are defined in multiple modules.
4165 if (moduleb->global_methods) {
4166 table = &assembly->tables [MONO_TABLE_METHOD];
4167 table->rows += mono_array_length (moduleb->global_methods);
4168 alloc_table (table, table->rows);
4169 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4170 mono_image_get_method_info (
4171 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4173 if (moduleb->global_fields) {
4174 table = &assembly->tables [MONO_TABLE_FIELD];
4175 table->rows += mono_array_length (moduleb->global_fields);
4176 alloc_table (table, table->rows);
4177 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4178 mono_image_get_field_info (
4179 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4182 table = &assembly->tables [MONO_TABLE_MODULE];
4183 alloc_table (table, 1);
4184 mono_image_fill_module_table (domain, moduleb, assembly);
4186 /* Collect all types into a list sorted by their table_idx */
4187 types = g_ptr_array_new ();
4190 for (i = 0; i < moduleb->num_types; ++i) {
4191 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4192 collect_types (types, type);
4195 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4196 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4197 table->rows += types->len;
4198 alloc_table (table, table->rows);
4201 * Emit type names + namespaces at one place inside the string heap,
4202 * so load_class_names () needs to touch fewer pages.
4204 for (i = 0; i < types->len; ++i) {
4205 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4206 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4208 for (i = 0; i < types->len; ++i) {
4209 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4210 string_heap_insert_mstring (&assembly->sheap, tb->name);
4213 for (i = 0; i < types->len; ++i) {
4214 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4215 mono_image_get_type_info (domain, type, assembly);
4219 * table->rows is already set above and in mono_image_fill_module_table.
4221 /* add all the custom attributes at the end, once all the indexes are stable */
4222 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4224 /* CAS assembly permissions */
4225 if (assemblyb->permissions_minimum)
4226 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4227 if (assemblyb->permissions_optional)
4228 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4229 if (assemblyb->permissions_refused)
4230 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4232 module_add_cattrs (assembly, moduleb);
4235 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4237 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4238 * the final tokens and don't need another fixup pass. */
4240 if (moduleb->global_methods) {
4241 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4242 MonoReflectionMethodBuilder *mb = mono_array_get (
4243 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4244 mono_image_add_methodimpl (assembly, mb);
4248 for (i = 0; i < types->len; ++i) {
4249 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4250 if (type->methods) {
4251 for (j = 0; j < type->num_methods; ++j) {
4252 MonoReflectionMethodBuilder *mb = mono_array_get (
4253 type->methods, MonoReflectionMethodBuilder*, j);
4255 mono_image_add_methodimpl (assembly, mb);
4260 g_ptr_array_free (types, TRUE);
4262 fixup_cattrs (assembly);
4266 * mono_image_insert_string:
4267 * @module: module builder object
4270 * Insert @str into the user string stream of @module.
4273 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4275 MonoDynamicImage *assembly;
4280 MONO_ARCH_SAVE_REGS;
4282 if (!module->dynamic_image)
4283 mono_image_module_basic_init (module);
4285 assembly = module->dynamic_image;
4287 if (assembly->save) {
4288 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4289 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4290 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4292 char *swapped = g_malloc (2 * mono_string_length (str));
4293 const char *p = (const char*)mono_string_chars (str);
4295 swap_with_size (swapped, p, 2, mono_string_length (str));
4296 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4300 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4302 mono_image_add_stream_data (&assembly->us, "", 1);
4304 idx = assembly->us.index ++;
4307 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4309 return MONO_TOKEN_STRING | idx;
4313 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4318 klass = obj->vtable->klass;
4319 if (strcmp (klass->name, "MonoMethod") == 0) {
4320 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4321 MonoMethodSignature *sig, *old;
4322 guint32 sig_token, parent;
4325 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4327 nargs = mono_array_length (opt_param_types);
4328 old = mono_method_signature (method);
4329 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4331 sig->hasthis = old->hasthis;
4332 sig->explicit_this = old->explicit_this;
4333 sig->call_convention = old->call_convention;
4334 sig->generic_param_count = old->generic_param_count;
4335 sig->param_count = old->param_count + nargs;
4336 sig->sentinelpos = old->param_count;
4337 sig->ret = old->ret;
4339 for (i = 0; i < old->param_count; i++)
4340 sig->params [i] = old->params [i];
4342 for (i = 0; i < nargs; i++) {
4343 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4344 sig->params [old->param_count + i] = rt->type;
4347 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4348 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4349 parent >>= MONO_TYPEDEFORREF_BITS;
4351 parent <<= MONO_MEMBERREF_PARENT_BITS;
4352 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4354 sig_token = method_encode_signature (assembly, sig);
4355 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4356 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4357 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4358 ReflectionMethodBuilder rmb;
4359 guint32 parent, sig;
4362 reflection_methodbuilder_from_method_builder (&rmb, mb);
4363 rmb.opt_types = opt_param_types;
4365 sig = method_builder_encode_signature (assembly, &rmb);
4367 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4368 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4370 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4371 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4373 name = mono_string_to_utf8 (rmb.name);
4374 token = mono_image_get_varargs_method_token (
4375 assembly, parent, name, sig);
4378 g_error ("requested method token for %s\n", klass->name);
4385 * mono_image_create_token:
4386 * @assembly: a dynamic assembly
4388 * @register_token: Whenever to register the token in the assembly->tokens hash.
4390 * Get a token to insert in the IL code stream for the given MemberInfo.
4391 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4392 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4396 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4397 gboolean create_methodspec, gboolean register_token)
4402 klass = obj->vtable->klass;
4403 if (strcmp (klass->name, "MethodBuilder") == 0) {
4404 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4405 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4407 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4408 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4410 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4411 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4412 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4413 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4414 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4416 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4417 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4419 token = mono_image_get_ctorbuilder_token (assembly, mb);
4420 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4421 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4422 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4423 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4424 if (tb->generic_params) {
4425 token = mono_image_get_generic_field_token (assembly, fb);
4427 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4429 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4430 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4431 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4432 } else if (strcmp (klass->name, "MonoType") == 0) {
4433 MonoReflectionType *tb = (MonoReflectionType *)obj;
4434 MonoClass *mc = mono_class_from_mono_type (tb->type);
4435 token = mono_metadata_token_from_dor (
4436 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4437 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4438 MonoReflectionType *tb = (MonoReflectionType *)obj;
4439 token = mono_metadata_token_from_dor (
4440 mono_image_typedef_or_ref (assembly, tb->type));
4441 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4442 MonoReflectionType *tb = (MonoReflectionType *)obj;
4443 token = mono_metadata_token_from_dor (
4444 mono_image_typedef_or_ref (assembly, tb->type));
4445 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4446 strcmp (klass->name, "MonoMethod") == 0 ||
4447 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4448 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4449 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4450 if (m->method->is_inflated) {
4451 if (create_methodspec)
4452 token = mono_image_get_methodspec_token (assembly, m->method);
4454 token = mono_image_get_inflated_method_token (assembly, m->method);
4455 } else if ((m->method->klass->image == &assembly->image) &&
4456 !m->method->klass->generic_class) {
4457 static guint32 method_table_idx = 0xffffff;
4458 if (m->method->klass->wastypebuilder) {
4459 /* we use the same token as the one that was assigned
4460 * to the Methodbuilder.
4461 * FIXME: do the equivalent for Fields.
4463 token = m->method->token;
4466 * Each token should have a unique index, but the indexes are
4467 * assigned by managed code, so we don't know about them. An
4468 * easy solution is to count backwards...
4470 method_table_idx --;
4471 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4474 token = mono_image_get_methodref_token (assembly, m->method);
4476 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4477 } else if (strcmp (klass->name, "MonoField") == 0) {
4478 MonoReflectionField *f = (MonoReflectionField *)obj;
4479 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4480 static guint32 field_table_idx = 0xffffff;
4482 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4484 token = mono_image_get_fieldref_token (assembly, f);
4486 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4487 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4488 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4489 token = mono_image_get_array_token (assembly, m);
4490 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4491 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4492 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4493 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4494 MonoReflectionType *tb = (MonoReflectionType *)obj;
4495 token = mono_metadata_token_from_dor (
4496 mono_image_typedef_or_ref (assembly, tb->type));
4497 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4498 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4499 token = mono_image_get_field_on_inst_token (assembly, f);
4500 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4501 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4502 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4503 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4504 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4505 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4507 g_error ("requested token for %s\n", klass->name);
4511 mono_image_register_token (assembly, token, obj);
4517 * mono_image_register_token:
4519 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4520 * the Module.ResolveXXXToken () methods to work.
4523 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4525 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4527 /* There could be multiple MethodInfo objects with the same token */
4528 //g_assert (prev == obj);
4530 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4535 guint32 import_lookup_table;
4539 guint32 import_address_table_rva;
4547 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4549 static MonoDynamicImage*
4550 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4552 static const guchar entrycode [16] = {0xff, 0x25, 0};
4553 MonoDynamicImage *image;
4556 const char *version;
4558 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4559 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4561 version = mono_get_runtime_info ()->runtime_version;
4564 image = GC_MALLOC (sizeof (MonoDynamicImage));
4566 image = g_new0 (MonoDynamicImage, 1);
4569 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4571 /*g_print ("created image %p\n", image);*/
4572 /* keep in sync with image.c */
4573 image->image.name = assembly_name;
4574 image->image.assembly_name = image->image.name; /* they may be different */
4575 image->image.module_name = module_name;
4576 image->image.version = g_strdup (version);
4577 image->image.md_version_major = 1;
4578 image->image.md_version_minor = 1;
4579 image->image.dynamic = TRUE;
4581 image->image.references = g_new0 (MonoAssembly*, 1);
4582 image->image.references [0] = NULL;
4584 mono_image_init (&image->image);
4586 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4587 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4588 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4589 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4590 image->handleref = g_hash_table_new (NULL, NULL);
4591 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4592 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4593 image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4594 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4595 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4596 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4597 image->gen_params = g_ptr_array_new ();
4599 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4600 string_heap_init (&image->sheap);
4601 mono_image_add_stream_data (&image->us, "", 1);
4602 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4603 /* import tables... */
4604 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4605 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4606 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4607 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4608 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4609 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4610 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4611 stream_data_align (&image->code);
4613 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4615 for (i=0; i < MONO_TABLE_NUM; ++i) {
4616 image->tables [i].next_idx = 1;
4617 image->tables [i].columns = table_sizes [i];
4620 image->image.assembly = (MonoAssembly*)assembly;
4621 image->run = assembly->run;
4622 image->save = assembly->save;
4623 image->pe_kind = 0x1; /* ILOnly */
4624 image->machine = 0x14c; /* I386 */
4626 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4632 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4638 mono_dynamic_image_free (MonoDynamicImage *image)
4640 MonoDynamicImage *di = image;
4645 mono_g_hash_table_destroy (di->methodspec);
4647 g_hash_table_destroy (di->typespec);
4649 g_hash_table_destroy (di->typeref);
4651 g_hash_table_destroy (di->handleref);
4653 mono_g_hash_table_destroy (di->tokens);
4654 if (di->generic_def_objects)
4655 mono_g_hash_table_destroy (di->generic_def_objects);
4656 if (di->blob_cache) {
4657 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4658 g_hash_table_destroy (di->blob_cache);
4660 for (list = di->array_methods; list; list = list->next) {
4661 ArrayMethod *am = (ArrayMethod *)list->data;
4666 g_list_free (di->array_methods);
4667 if (di->gen_params) {
4668 for (i = 0; i < di->gen_params->len; i++) {
4669 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4670 if (entry->gparam->type.type) {
4671 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4672 g_free ((char*)param->name);
4674 g_free (entry->gparam->type.type);
4678 g_ptr_array_free (di->gen_params, TRUE);
4680 if (di->token_fixups)
4681 mono_g_hash_table_destroy (di->token_fixups);
4682 if (di->method_to_table_idx)
4683 g_hash_table_destroy (di->method_to_table_idx);
4684 if (di->field_to_table_idx)
4685 g_hash_table_destroy (di->field_to_table_idx);
4686 if (di->method_aux_hash)
4687 g_hash_table_destroy (di->method_aux_hash);
4688 g_free (di->strong_name);
4689 g_free (di->win32_res);
4691 g_free (di->public_key);
4693 /*g_print ("string heap destroy for image %p\n", di);*/
4694 mono_dynamic_stream_reset (&di->sheap);
4695 mono_dynamic_stream_reset (&di->code);
4696 mono_dynamic_stream_reset (&di->resources);
4697 mono_dynamic_stream_reset (&di->us);
4698 mono_dynamic_stream_reset (&di->blob);
4699 mono_dynamic_stream_reset (&di->tstream);
4700 mono_dynamic_stream_reset (&di->guid);
4701 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4702 g_free (di->tables [i].values);
4707 * mono_image_basic_init:
4708 * @assembly: an assembly builder object
4710 * Create the MonoImage that represents the assembly builder and setup some
4711 * of the helper hash table and the basic metadata streams.
4714 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4716 MonoDynamicAssembly *assembly;
4717 MonoDynamicImage *image;
4718 MonoDomain *domain = mono_object_domain (assemblyb);
4720 MONO_ARCH_SAVE_REGS;
4722 if (assemblyb->dynamic_assembly)
4726 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4728 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4731 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4733 assembly->assembly.ref_count = 1;
4734 assembly->assembly.dynamic = TRUE;
4735 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4736 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4737 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4738 if (assemblyb->culture)
4739 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4741 assembly->assembly.aname.culture = g_strdup ("");
4743 if (assemblyb->version) {
4744 char *vstr = mono_string_to_utf8 (assemblyb->version);
4745 char **version = g_strsplit (vstr, ".", 4);
4746 char **parts = version;
4747 assembly->assembly.aname.major = atoi (*parts++);
4748 assembly->assembly.aname.minor = atoi (*parts++);
4749 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4750 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4752 g_strfreev (version);
4755 assembly->assembly.aname.major = 0;
4756 assembly->assembly.aname.minor = 0;
4757 assembly->assembly.aname.build = 0;
4758 assembly->assembly.aname.revision = 0;
4761 assembly->run = assemblyb->access != 2;
4762 assembly->save = assemblyb->access != 1;
4764 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4765 image->initial_image = TRUE;
4766 assembly->assembly.aname.name = image->image.name;
4767 assembly->assembly.image = &image->image;
4769 mono_domain_assemblies_lock (domain);
4770 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4771 mono_domain_assemblies_unlock (domain);
4773 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4775 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4777 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4781 calc_section_size (MonoDynamicImage *assembly)
4785 /* alignment constraints */
4786 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4787 g_assert ((assembly->code.index % 4) == 0);
4788 assembly->meta_size += 3;
4789 assembly->meta_size &= ~3;
4790 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4791 g_assert ((assembly->resources.index % 4) == 0);
4793 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4794 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4797 if (assembly->win32_res) {
4798 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4800 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4801 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4805 assembly->sections [MONO_SECTION_RELOC].size = 12;
4806 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4816 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4820 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4822 ResTreeNode *t1 = (ResTreeNode*)a;
4823 ResTreeNode *t2 = (ResTreeNode*)b;
4825 return t1->id - t2->id;
4829 * resource_tree_create:
4831 * Organize the resources into a resource tree.
4833 static ResTreeNode *
4834 resource_tree_create (MonoArray *win32_resources)
4836 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4840 tree = g_new0 (ResTreeNode, 1);
4842 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4843 MonoReflectionWin32Resource *win32_res =
4844 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4848 /* FIXME: BUG: this stores managed references in unmanaged memory */
4849 lang_node = g_new0 (ResTreeNode, 1);
4850 lang_node->id = win32_res->lang_id;
4851 lang_node->win32_res = win32_res;
4853 /* Create type node if neccesary */
4855 for (l = tree->children; l; l = l->next)
4856 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4857 type_node = (ResTreeNode*)l->data;
4862 type_node = g_new0 (ResTreeNode, 1);
4863 type_node->id = win32_res->res_type;
4866 * The resource types have to be sorted otherwise
4867 * Windows Explorer can't display the version information.
4869 tree->children = g_slist_insert_sorted (tree->children,
4870 type_node, resource_tree_compare_by_id);
4873 /* Create res node if neccesary */
4875 for (l = type_node->children; l; l = l->next)
4876 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4877 res_node = (ResTreeNode*)l->data;
4882 res_node = g_new0 (ResTreeNode, 1);
4883 res_node->id = win32_res->res_id;
4884 type_node->children = g_slist_append (type_node->children, res_node);
4887 res_node->children = g_slist_append (res_node->children, lang_node);
4894 * resource_tree_encode:
4896 * Encode the resource tree into the format used in the PE file.
4899 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4902 MonoPEResourceDir dir;
4903 MonoPEResourceDirEntry dir_entry;
4904 MonoPEResourceDataEntry data_entry;
4908 * For the format of the resource directory, see the article
4909 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4913 memset (&dir, 0, sizeof (dir));
4914 memset (&dir_entry, 0, sizeof (dir_entry));
4915 memset (&data_entry, 0, sizeof (data_entry));
4917 g_assert (sizeof (dir) == 16);
4918 g_assert (sizeof (dir_entry) == 8);
4919 g_assert (sizeof (data_entry) == 16);
4921 node->offset = p - begin;
4923 /* IMAGE_RESOURCE_DIRECTORY */
4924 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4926 memcpy (p, &dir, sizeof (dir));
4929 /* Reserve space for entries */
4931 p += sizeof (dir_entry) * dir.res_id_entries;
4933 /* Write children */
4934 for (l = node->children; l; l = l->next) {
4935 ResTreeNode *child = (ResTreeNode*)l->data;
4937 if (child->win32_res) {
4939 child->offset = p - begin;
4941 /* IMAGE_RESOURCE_DATA_ENTRY */
4942 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4943 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4945 memcpy (p, &data_entry, sizeof (data_entry));
4946 p += sizeof (data_entry);
4948 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4949 p += data_entry.rde_size;
4951 resource_tree_encode (child, begin, p, &p);
4955 /* IMAGE_RESOURCE_ENTRY */
4956 for (l = node->children; l; l = l->next) {
4957 ResTreeNode *child = (ResTreeNode*)l->data;
4958 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4960 dir_entry.is_dir = child->win32_res ? 0 : 1;
4961 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4963 memcpy (entries, &dir_entry, sizeof (dir_entry));
4964 entries += sizeof (dir_entry);
4971 resource_tree_free (ResTreeNode * node)
4974 for (list = node->children; list; list = list->next)
4975 resource_tree_free ((ResTreeNode*)list->data);
4976 g_slist_free(node->children);
4981 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4986 MonoReflectionWin32Resource *win32_res;
4989 if (!assemblyb->win32_resources)
4993 * Resources are stored in a three level tree inside the PE file.
4994 * - level one contains a node for each type of resource
4995 * - level two contains a node for each resource
4996 * - level three contains a node for each instance of a resource for a
4997 * specific language.
5000 tree = resource_tree_create (assemblyb->win32_resources);
5002 /* Estimate the size of the encoded tree */
5004 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5005 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5006 size += mono_array_length (win32_res->res_data);
5008 /* Directory structure */
5009 size += mono_array_length (assemblyb->win32_resources) * 256;
5010 p = buf = g_malloc (size);
5012 resource_tree_encode (tree, p, p, &p);
5014 g_assert (p - buf <= size);
5016 assembly->win32_res = g_malloc (p - buf);
5017 assembly->win32_res_size = p - buf;
5018 memcpy (assembly->win32_res, buf, p - buf);
5021 resource_tree_free (tree);
5025 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5027 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5030 p += sizeof (MonoPEResourceDir);
5031 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
5032 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5033 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
5034 if (dir_entry->is_dir) {
5035 fixup_resource_directory (res_section, child, rva);
5037 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5038 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5041 p += sizeof (MonoPEResourceDirEntry);
5046 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5049 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5050 g_error ("WriteFile returned %d\n", GetLastError ());
5054 * mono_image_create_pefile:
5055 * @mb: a module builder object
5057 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5058 * assembly->pefile where it can be easily retrieved later in chunks.
5061 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
5062 MonoMSDOSHeader *msdos;
5063 MonoDotNetHeader *header;
5064 MonoSectionTable *section;
5065 MonoCLIHeader *cli_header;
5066 guint32 size, image_size, virtual_base, text_offset;
5067 guint32 header_start, section_start, file_offset, virtual_offset;
5068 MonoDynamicImage *assembly;
5069 MonoReflectionAssemblyBuilder *assemblyb;
5070 MonoDynamicStream pefile_stream = {0};
5071 MonoDynamicStream *pefile = &pefile_stream;
5073 guint32 *rva, value;
5075 static const unsigned char msheader[] = {
5076 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5077 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5078 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5079 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5080 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5081 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5082 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5083 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5086 assemblyb = mb->assemblyb;
5088 mono_image_basic_init (assemblyb);
5089 assembly = mb->dynamic_image;
5091 assembly->pe_kind = assemblyb->pe_kind;
5092 assembly->machine = assemblyb->machine;
5093 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5094 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5096 mono_image_build_metadata (mb);
5098 if (mb->is_main && assemblyb->resources) {
5099 int len = mono_array_length (assemblyb->resources);
5100 for (i = 0; i < len; ++i)
5101 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5104 if (mb->resources) {
5105 int len = mono_array_length (mb->resources);
5106 for (i = 0; i < len; ++i)
5107 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5110 build_compressed_metadata (assembly);
5113 assembly_add_win32_resources (assembly, assemblyb);
5115 nsections = calc_section_size (assembly);
5117 /* The DOS header and stub */
5118 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5119 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5121 /* the dotnet header */
5122 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5124 /* the section tables */
5125 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5127 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5128 virtual_offset = VIRT_ALIGN;
5131 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5132 if (!assembly->sections [i].size)
5135 file_offset += FILE_ALIGN - 1;
5136 file_offset &= ~(FILE_ALIGN - 1);
5137 virtual_offset += VIRT_ALIGN - 1;
5138 virtual_offset &= ~(VIRT_ALIGN - 1);
5140 assembly->sections [i].offset = file_offset;
5141 assembly->sections [i].rva = virtual_offset;
5143 file_offset += assembly->sections [i].size;
5144 virtual_offset += assembly->sections [i].size;
5145 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5148 file_offset += FILE_ALIGN - 1;
5149 file_offset &= ~(FILE_ALIGN - 1);
5151 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5153 /* back-patch info */
5154 msdos = (MonoMSDOSHeader*)pefile->data;
5155 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5157 header = (MonoDotNetHeader*)(pefile->data + header_start);
5158 header->pesig [0] = 'P';
5159 header->pesig [1] = 'E';
5161 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5162 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5163 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5164 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5165 if (assemblyb->pekind == 1) {
5167 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5170 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5173 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5175 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5176 header->pe.pe_major = 6;
5177 header->pe.pe_minor = 0;
5178 size = assembly->sections [MONO_SECTION_TEXT].size;
5179 size += FILE_ALIGN - 1;
5180 size &= ~(FILE_ALIGN - 1);
5181 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5182 size = assembly->sections [MONO_SECTION_RSRC].size;
5183 size += FILE_ALIGN - 1;
5184 size &= ~(FILE_ALIGN - 1);
5185 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5186 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5187 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5188 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5189 /* pe_rva_entry_point always at the beginning of the text section */
5190 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5192 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5193 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5194 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5195 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5196 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5197 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5198 size = section_start;
5199 size += FILE_ALIGN - 1;
5200 size &= ~(FILE_ALIGN - 1);
5201 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5203 size += VIRT_ALIGN - 1;
5204 size &= ~(VIRT_ALIGN - 1);
5205 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5208 // Translate the PEFileKind value to the value expected by the Windows loader
5214 // PEFileKinds.Dll == 1
5215 // PEFileKinds.ConsoleApplication == 2
5216 // PEFileKinds.WindowApplication == 3
5219 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5220 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5222 if (assemblyb->pekind == 3)
5227 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5229 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5230 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5231 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5232 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5233 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5234 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5236 /* fill data directory entries */
5238 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5239 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5241 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5242 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5244 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5245 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5246 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5247 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5248 /* patch entrypoint name */
5249 if (assemblyb->pekind == 1)
5250 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5252 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5253 /* patch imported function RVA name */
5254 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5255 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5257 /* the import table */
5258 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5259 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5260 /* patch imported dll RVA name and other entries in the dir */
5261 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5262 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5263 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5264 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5265 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5266 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5268 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5269 value = (assembly->text_rva + assembly->imp_names_offset);
5270 *p++ = (value) & 0xff;
5271 *p++ = (value >> 8) & (0xff);
5272 *p++ = (value >> 16) & (0xff);
5273 *p++ = (value >> 24) & (0xff);
5275 /* the CLI header info */
5276 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5277 cli_header->ch_size = GUINT32_FROM_LE (72);
5278 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5279 if (mono_get_runtime_info ()->framework_version [0] > '1')
5280 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5282 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5283 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5284 if (assemblyb->entry_point) {
5285 guint32 table_idx = 0;
5286 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5287 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5288 table_idx = methodb->table_idx;
5290 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5292 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5294 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5296 /* The embedded managed resources */
5297 text_offset = assembly->text_rva + assembly->code.index;
5298 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5299 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5300 text_offset += assembly->resources.index;
5301 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5302 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5303 text_offset += assembly->meta_size;
5304 if (assembly->strong_name_size) {
5305 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5306 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5307 text_offset += assembly->strong_name_size;
5310 /* write the section tables and section content */
5311 section = (MonoSectionTable*)(pefile->data + section_start);
5312 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5313 static const char section_names [][7] = {
5314 ".text", ".rsrc", ".reloc"
5316 if (!assembly->sections [i].size)
5318 strcpy (section->st_name, section_names [i]);
5319 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5320 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5321 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5322 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5323 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5324 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5325 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5329 checked_write_file (file, pefile->data, pefile->index);
5331 mono_dynamic_stream_reset (pefile);
5333 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5334 if (!assembly->sections [i].size)
5337 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5338 g_error ("SetFilePointer returned %d\n", GetLastError ());
5341 case MONO_SECTION_TEXT:
5342 /* patch entry point */
5343 p = (guchar*)(assembly->code.data + 2);
5344 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5345 *p++ = (value) & 0xff;
5346 *p++ = (value >> 8) & 0xff;
5347 *p++ = (value >> 16) & 0xff;
5348 *p++ = (value >> 24) & 0xff;
5350 checked_write_file (file, assembly->code.data, assembly->code.index);
5351 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5352 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5353 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5356 g_free (assembly->image.raw_metadata);
5358 case MONO_SECTION_RELOC: {
5362 guint16 type_and_offset;
5366 g_assert (sizeof (reloc) == 12);
5368 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5369 reloc.block_size = GUINT32_FROM_LE (12);
5372 * the entrypoint is always at the start of the text section
5373 * 3 is IMAGE_REL_BASED_HIGHLOW
5374 * 2 is patch_size_rva - text_rva
5376 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5379 checked_write_file (file, &reloc, sizeof (reloc));
5383 case MONO_SECTION_RSRC:
5384 if (assembly->win32_res) {
5386 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5387 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5388 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5392 g_assert_not_reached ();
5396 /* check that the file is properly padded */
5397 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5398 g_error ("SetFilePointer returned %d\n", GetLastError ());
5399 if (! SetEndOfFile (file))
5400 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5402 mono_dynamic_stream_reset (&assembly->code);
5403 mono_dynamic_stream_reset (&assembly->us);
5404 mono_dynamic_stream_reset (&assembly->blob);
5405 mono_dynamic_stream_reset (&assembly->guid);
5406 mono_dynamic_stream_reset (&assembly->sheap);
5408 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5409 g_hash_table_destroy (assembly->blob_cache);
5410 assembly->blob_cache = NULL;
5413 MonoReflectionModule *
5414 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5418 MonoImageOpenStatus status;
5419 MonoDynamicAssembly *assembly;
5420 guint32 module_count;
5421 MonoImage **new_modules;
5422 gboolean *new_modules_loaded;
5424 name = mono_string_to_utf8 (fileName);
5426 image = mono_image_open (name, &status);
5429 if (status == MONO_IMAGE_ERROR_ERRNO)
5430 exc = mono_get_exception_file_not_found (fileName);
5432 exc = mono_get_exception_bad_image_format (name);
5434 mono_raise_exception (exc);
5439 assembly = ab->dynamic_assembly;
5440 image->assembly = (MonoAssembly*)assembly;
5442 module_count = image->assembly->image->module_count;
5443 new_modules = g_new0 (MonoImage *, module_count + 1);
5444 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5446 if (image->assembly->image->modules)
5447 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5448 if (image->assembly->image->modules_loaded)
5449 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5450 new_modules [module_count] = image;
5451 new_modules_loaded [module_count] = TRUE;
5452 mono_image_addref (image);
5454 g_free (image->assembly->image->modules);
5455 image->assembly->image->modules = new_modules;
5456 image->assembly->image->modules_loaded = new_modules_loaded;
5457 image->assembly->image->module_count ++;
5459 mono_assembly_load_references (image, &status);
5461 mono_image_close (image);
5462 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5465 return mono_module_get_object (mono_domain_get (), image);
5469 * We need to return always the same object for MethodInfo, FieldInfo etc..
5470 * but we need to consider the reflected type.
5471 * type uses a different hash, since it uses custom hash/equal functions.
5476 MonoClass *refclass;
5480 reflected_equal (gconstpointer a, gconstpointer b) {
5481 const ReflectedEntry *ea = a;
5482 const ReflectedEntry *eb = b;
5484 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5488 reflected_hash (gconstpointer a) {
5489 const ReflectedEntry *ea = a;
5490 return mono_aligned_addr_hash (ea->item);
5493 #define CHECK_OBJECT(t,p,k) \
5499 mono_domain_lock (domain); \
5500 if (!domain->refobject_hash) \
5501 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5502 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5503 mono_domain_unlock (domain); \
5506 mono_domain_unlock (domain); \
5509 #ifndef HAVE_NULL_GC
5510 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5512 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5515 #define CACHE_OBJECT(t,p,o,k) \
5518 ReflectedEntry pe; \
5520 pe.refclass = (k); \
5521 mono_domain_lock (domain); \
5522 if (!domain->refobject_hash) \
5523 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5524 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5526 ReflectedEntry *e = ALLOC_REFENTRY; \
5528 e->refclass = (k); \
5529 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5532 mono_domain_unlock (domain); \
5537 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5539 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5543 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5545 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5549 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5551 MonoDynamicImage *image = moduleb->dynamic_image;
5552 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5555 MonoImage **new_modules;
5558 * FIXME: we already created an image in mono_image_basic_init (), but
5559 * we don't know which module it belongs to, since that is only
5560 * determined at assembly save time.
5562 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5563 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5565 moduleb->module.image = &image->image;
5566 moduleb->dynamic_image = image;
5567 register_module (mono_object_domain (moduleb), moduleb, image);
5569 /* register the module with the assembly */
5570 ass = ab->dynamic_assembly->assembly.image;
5571 module_count = ass->module_count;
5572 new_modules = g_new0 (MonoImage *, module_count + 1);
5575 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5576 new_modules [module_count] = &image->image;
5577 mono_image_addref (&image->image);
5579 g_free (ass->modules);
5580 ass->modules = new_modules;
5581 ass->module_count ++;
5586 * mono_assembly_get_object:
5587 * @domain: an app domain
5588 * @assembly: an assembly
5590 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5592 MonoReflectionAssembly*
5593 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5595 static MonoClass *System_Reflection_Assembly;
5596 MonoReflectionAssembly *res;
5598 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5599 if (!System_Reflection_Assembly)
5600 System_Reflection_Assembly = mono_class_from_name (
5601 mono_defaults.corlib, "System.Reflection", "Assembly");
5602 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5603 res->assembly = assembly;
5605 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5610 MonoReflectionModule*
5611 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5613 static MonoClass *System_Reflection_Module;
5614 MonoReflectionModule *res;
5617 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5618 if (!System_Reflection_Module)
5619 System_Reflection_Module = mono_class_from_name (
5620 mono_defaults.corlib, "System.Reflection", "Module");
5621 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5624 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5626 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5627 basename = g_path_get_basename (image->name);
5628 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5629 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5633 if (image->assembly->image == image) {
5634 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5638 if (image->assembly->image->modules) {
5639 for (i = 0; i < image->assembly->image->module_count; i++) {
5640 if (image->assembly->image->modules [i] == image)
5641 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5643 g_assert (res->token);
5647 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5650 MonoReflectionModule*
5651 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5653 static MonoClass *System_Reflection_Module;
5654 MonoReflectionModule *res;
5655 MonoTableInfo *table;
5656 guint32 cols [MONO_FILE_SIZE];
5658 guint32 i, name_idx;
5661 if (!System_Reflection_Module)
5662 System_Reflection_Module = mono_class_from_name (
5663 mono_defaults.corlib, "System.Reflection", "Module");
5664 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5666 table = &image->tables [MONO_TABLE_FILE];
5667 g_assert (table_index < table->rows);
5668 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5671 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5672 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5674 /* Check whenever the row has a corresponding row in the moduleref table */
5675 table = &image->tables [MONO_TABLE_MODULEREF];
5676 for (i = 0; i < table->rows; ++i) {
5677 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5678 val = mono_metadata_string_heap (image, name_idx);
5679 if (strcmp (val, name) == 0)
5680 res->image = image->modules [i];
5683 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5684 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5685 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5686 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5687 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5693 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5695 if ((t1->type != t2->type) ||
5696 (t1->byref != t2->byref))
5700 case MONO_TYPE_VOID:
5701 case MONO_TYPE_BOOLEAN:
5702 case MONO_TYPE_CHAR:
5713 case MONO_TYPE_STRING:
5716 case MONO_TYPE_OBJECT:
5717 case MONO_TYPE_TYPEDBYREF:
5719 case MONO_TYPE_VALUETYPE:
5720 case MONO_TYPE_CLASS:
5721 case MONO_TYPE_SZARRAY:
5722 return t1->data.klass == t2->data.klass;
5724 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5725 case MONO_TYPE_ARRAY:
5726 if (t1->data.array->rank != t2->data.array->rank)
5728 return t1->data.array->eklass == t2->data.array->eklass;
5729 case MONO_TYPE_GENERICINST: {
5731 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5732 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5733 if (i1->type_argc != i2->type_argc)
5735 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5736 &t2->data.generic_class->container_class->byval_arg))
5738 /* FIXME: we should probably just compare the instance pointers directly. */
5739 for (i = 0; i < i1->type_argc; ++i) {
5740 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5746 case MONO_TYPE_MVAR:
5747 return t1->data.generic_param == t2->data.generic_param;
5749 g_error ("implement type compare for %0x!", t1->type);
5757 mymono_metadata_type_hash (MonoType *t1)
5763 hash |= t1->byref << 6; /* do not collide with t1->type values */
5765 case MONO_TYPE_VALUETYPE:
5766 case MONO_TYPE_CLASS:
5767 case MONO_TYPE_SZARRAY:
5768 /* check if the distribution is good enough */
5769 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5771 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5772 case MONO_TYPE_GENERICINST: {
5774 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5775 hash += g_str_hash (t1->data.generic_class->container_class->name);
5777 for (i = 0; i < inst->type_argc; ++i) {
5778 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5787 static MonoReflectionGenericClass*
5788 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5790 static MonoClass *System_Reflection_MonoGenericClass;
5791 MonoReflectionGenericClass *res;
5792 MonoClass *klass, *gklass;
5794 if (!System_Reflection_MonoGenericClass) {
5795 System_Reflection_MonoGenericClass = mono_class_from_name (
5796 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5797 g_assert (System_Reflection_MonoGenericClass);
5800 klass = mono_class_from_mono_type (geninst);
5801 gklass = klass->generic_class->container_class;
5803 mono_class_init (klass);
5806 /* FIXME: allow unpinned later */
5807 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5809 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5812 res->type.type = geninst;
5813 g_assert (gklass->reflection_info);
5814 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
5815 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5821 verify_safe_for_managed_space (MonoType *type)
5823 switch (type->type) {
5825 case MONO_TYPE_ARRAY:
5826 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5828 return verify_safe_for_managed_space (type->data.type);
5829 case MONO_TYPE_SZARRAY:
5830 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5831 case MONO_TYPE_GENERICINST: {
5832 MonoGenericInst *inst = type->data.generic_class->inst;
5836 for (i = 0; i < inst->type_argc; ++i)
5837 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5843 case MONO_TYPE_MVAR:
5850 * mono_type_get_object:
5851 * @domain: an app domain
5854 * Return an System.MonoType object representing the type @type.
5857 mono_type_get_object (MonoDomain *domain, MonoType *type)
5859 MonoReflectionType *res;
5860 MonoClass *klass = mono_class_from_mono_type (type);
5862 /*we must avoid using @type as it might have come
5863 * from a mono_metadata_type_dup and the caller
5864 * expects that is can be freed.
5865 * Using the right type from
5867 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
5870 * If the vtable of the given class was already created, we can use
5871 * the MonoType from there and avoid all locking and hash table lookups.
5873 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
5874 * that the resulting object is diferent.
5876 if (type == &klass->byval_arg && !klass->image->dynamic) {
5877 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
5878 if (vtable && vtable->type)
5879 return vtable->type;
5882 mono_domain_lock (domain);
5883 if (!domain->type_hash)
5884 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5885 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5886 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5887 mono_domain_unlock (domain);
5890 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
5891 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
5892 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5893 mono_g_hash_table_insert (domain->type_hash, type, res);
5894 mono_domain_unlock (domain);
5898 if (!verify_safe_for_managed_space (type)) {
5899 mono_domain_unlock (domain);
5900 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5903 if (klass->reflection_info && !klass->wastypebuilder) {
5904 /* g_assert_not_reached (); */
5905 /* should this be considered an error condition? */
5907 mono_domain_unlock (domain);
5908 return klass->reflection_info;
5911 // FIXME: Get rid of this, do it in the icalls for Type
5912 mono_class_init (klass);
5914 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5916 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5919 mono_g_hash_table_insert (domain->type_hash, type, res);
5920 mono_domain_unlock (domain);
5925 * mono_method_get_object:
5926 * @domain: an app domain
5928 * @refclass: the reflected type (can be NULL)
5930 * Return an System.Reflection.MonoMethod object representing the method @method.
5932 MonoReflectionMethod*
5933 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5936 * We use the same C representation for methods and constructors, but the type
5937 * name in C# is different.
5939 static MonoClass *System_Reflection_MonoMethod = NULL;
5940 static MonoClass *System_Reflection_MonoCMethod = NULL;
5941 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5942 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5944 MonoReflectionMethod *ret;
5947 * Don't let static RGCTX invoke wrappers get into
5948 * MonoReflectionMethods.
5950 if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
5951 method = mono_marshal_method_from_wrapper (method);
5953 if (method->is_inflated) {
5954 MonoReflectionGenericMethod *gret;
5956 refclass = method->klass;
5957 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5958 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5959 if (!System_Reflection_MonoGenericCMethod)
5960 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5961 klass = System_Reflection_MonoGenericCMethod;
5963 if (!System_Reflection_MonoGenericMethod)
5964 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5965 klass = System_Reflection_MonoGenericMethod;
5967 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5968 gret->method.method = method;
5969 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5970 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5971 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5975 refclass = method->klass;
5977 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5978 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5979 if (!System_Reflection_MonoCMethod)
5980 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5981 klass = System_Reflection_MonoCMethod;
5984 if (!System_Reflection_MonoMethod)
5985 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5986 klass = System_Reflection_MonoMethod;
5988 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5989 ret->method = method;
5990 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5991 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5995 * mono_field_get_object:
5996 * @domain: an app domain
6000 * Return an System.Reflection.MonoField object representing the field @field
6003 MonoReflectionField*
6004 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6006 MonoReflectionField *res;
6007 static MonoClass *monofield_klass;
6009 CHECK_OBJECT (MonoReflectionField *, field, klass);
6010 if (!monofield_klass)
6011 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6012 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6015 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
6016 if (field->generic_info)
6017 res->attrs = field->generic_info->generic_type->attrs;
6019 res->attrs = field->type->attrs;
6020 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6021 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6025 * mono_property_get_object:
6026 * @domain: an app domain
6028 * @property: a property
6030 * Return an System.Reflection.MonoProperty object representing the property @property
6033 MonoReflectionProperty*
6034 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6036 MonoReflectionProperty *res;
6037 static MonoClass *monoproperty_klass;
6039 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6040 if (!monoproperty_klass)
6041 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6042 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6044 res->property = property;
6045 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6049 * mono_event_get_object:
6050 * @domain: an app domain
6054 * Return an System.Reflection.MonoEvent object representing the event @event
6057 MonoReflectionEvent*
6058 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6060 MonoReflectionEvent *res;
6061 static MonoClass *monoevent_klass;
6063 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6064 if (!monoevent_klass)
6065 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6066 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6069 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6073 * mono_get_reflection_missing_object:
6074 * @domain: Domain where the object lives
6076 * Returns the System.Reflection.Missing.Value singleton object
6077 * (of type System.Reflection.Missing).
6079 * Used as the value for ParameterInfo.DefaultValue when Optional
6083 mono_get_reflection_missing_object (MonoDomain *domain)
6086 static MonoClassField *missing_value_field = NULL;
6088 if (!missing_value_field) {
6089 MonoClass *missing_klass;
6090 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6091 mono_class_init (missing_klass);
6092 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6093 g_assert (missing_value_field);
6095 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6101 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6104 *dbnull = mono_get_dbnull_object (domain);
6109 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6111 if (!*reflection_missing)
6112 *reflection_missing = mono_get_reflection_missing_object (domain);
6113 return *reflection_missing;
6117 * mono_param_get_objects:
6118 * @domain: an app domain
6121 * Return an System.Reflection.ParameterInfo array object representing the parameters
6122 * in the method @method.
6125 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6127 static MonoClass *System_Reflection_ParameterInfo;
6128 static MonoClass *System_Reflection_ParameterInfo_array;
6129 MonoArray *res = NULL;
6130 MonoReflectionMethod *member = NULL;
6131 MonoReflectionParameter *param = NULL;
6132 char **names, **blobs = NULL;
6133 guint32 *types = NULL;
6134 MonoType *type = NULL;
6135 MonoObject *dbnull = NULL;
6136 MonoObject *missing = NULL;
6137 MonoMarshalSpec **mspecs;
6138 MonoMethodSignature *sig;
6139 MonoVTable *pinfo_vtable;
6142 if (!System_Reflection_ParameterInfo_array) {
6145 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6146 mono_memory_barrier ();
6147 System_Reflection_ParameterInfo = klass;
6149 klass = mono_array_class_get (klass, 1);
6150 mono_memory_barrier ();
6151 System_Reflection_ParameterInfo_array = klass;
6154 if (!mono_method_signature (method)->param_count)
6155 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6157 /* Note: the cache is based on the address of the signature into the method
6158 * since we already cache MethodInfos with the method as keys.
6160 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6162 sig = mono_method_signature (method);
6163 member = mono_method_get_object (domain, method, NULL);
6164 names = g_new (char *, sig->param_count);
6165 mono_method_get_param_names (method, (const char **) names);
6167 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6168 mono_method_get_marshal_info (method, mspecs);
6170 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6171 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6172 for (i = 0; i < sig->param_count; ++i) {
6173 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6174 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6175 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6176 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6177 param->PositionImpl = i;
6178 param->AttrsImpl = sig->params [i]->attrs;
6180 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6181 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6182 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6184 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6188 blobs = g_new0 (char *, sig->param_count);
6189 types = g_new0 (guint32, sig->param_count);
6190 get_default_param_value_blobs (method, blobs, types);
6193 /* Build MonoType for the type from the Constant Table */
6195 type = g_new0 (MonoType, 1);
6196 type->type = types [i];
6197 type->data.klass = NULL;
6198 if (types [i] == MONO_TYPE_CLASS)
6199 type->data.klass = mono_defaults.object_class;
6200 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6201 /* For enums, types [i] contains the base type */
6203 type->type = MONO_TYPE_VALUETYPE;
6204 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6206 type->data.klass = mono_class_from_mono_type (type);
6208 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6210 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6211 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6212 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6213 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6215 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6221 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6223 mono_array_setref (res, i, param);
6230 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6232 mono_metadata_free_marshal_spec (mspecs [i]);
6235 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6239 * mono_method_body_get_object:
6240 * @domain: an app domain
6243 * Return an System.Reflection.MethodBody object representing the method @method.
6245 MonoReflectionMethodBody*
6246 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6248 static MonoClass *System_Reflection_MethodBody = NULL;
6249 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6250 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6251 MonoReflectionMethodBody *ret;
6252 MonoMethodNormal *mn;
6253 MonoMethodHeader *header;
6254 guint32 method_rva, local_var_sig_token;
6256 unsigned char format, flags;
6259 if (!System_Reflection_MethodBody)
6260 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6261 if (!System_Reflection_LocalVariableInfo)
6262 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6263 if (!System_Reflection_ExceptionHandlingClause)
6264 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6266 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6268 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6269 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6270 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6271 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6273 mn = (MonoMethodNormal *)method;
6274 header = mono_method_get_header (method);
6276 /* Obtain local vars signature token */
6277 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6278 ptr = mono_image_rva_map (method->klass->image, method_rva);
6279 flags = *(const unsigned char *) ptr;
6280 format = flags & METHOD_HEADER_FORMAT_MASK;
6282 case METHOD_HEADER_TINY_FORMAT:
6283 case METHOD_HEADER_TINY_FORMAT1:
6284 local_var_sig_token = 0;
6286 case METHOD_HEADER_FAT_FORMAT:
6290 local_var_sig_token = read32 (ptr);
6293 g_assert_not_reached ();
6296 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6298 ret->init_locals = header->init_locals;
6299 ret->max_stack = header->max_stack;
6300 ret->local_var_sig_token = local_var_sig_token;
6301 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6302 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6305 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6306 for (i = 0; i < header->num_locals; ++i) {
6307 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6308 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6309 info->is_pinned = header->locals [i]->pinned;
6310 info->local_index = i;
6311 mono_array_setref (ret->locals, i, info);
6315 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6316 for (i = 0; i < header->num_clauses; ++i) {
6317 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6318 MonoExceptionClause *clause = &header->clauses [i];
6320 info->flags = clause->flags;
6321 info->try_offset = clause->try_offset;
6322 info->try_length = clause->try_len;
6323 info->handler_offset = clause->handler_offset;
6324 info->handler_length = clause->handler_len;
6325 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6326 info->filter_offset = clause->data.filter_offset;
6327 else if (clause->data.catch_class)
6328 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6330 mono_array_setref (ret->clauses, i, info);
6333 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6338 * mono_get_dbnull_object:
6339 * @domain: Domain where the object lives
6341 * Returns the System.DBNull.Value singleton object
6343 * Used as the value for ParameterInfo.DefaultValue
6346 mono_get_dbnull_object (MonoDomain *domain)
6349 static MonoClassField *dbnull_value_field = NULL;
6351 if (!dbnull_value_field) {
6352 MonoClass *dbnull_klass;
6353 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6354 mono_class_init (dbnull_klass);
6355 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6356 g_assert (dbnull_value_field);
6358 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6364 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6366 guint32 param_index, i, lastp, crow = 0;
6367 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6370 MonoClass *klass = method->klass;
6371 MonoImage *image = klass->image;
6372 MonoMethodSignature *methodsig = mono_method_signature (method);
6374 MonoTableInfo *constt;
6375 MonoTableInfo *methodt;
6376 MonoTableInfo *paramt;
6378 if (!methodsig->param_count)
6381 mono_class_init (klass);
6383 if (klass->image->dynamic) {
6384 MonoReflectionMethodAux *aux;
6385 if (method->is_inflated)
6386 method = ((MonoMethodInflated*)method)->declaring;
6387 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6388 if (aux && aux->param_defaults) {
6389 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6390 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6395 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6396 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6397 constt = &image->tables [MONO_TABLE_CONSTANT];
6399 idx = mono_method_get_index (method) - 1;
6400 g_assert (idx != -1);
6402 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6403 if (idx + 1 < methodt->rows)
6404 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6406 lastp = paramt->rows + 1;
6408 for (i = param_index; i < lastp; ++i) {
6411 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6412 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6414 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6417 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6422 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6423 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6424 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6431 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6436 MonoType *basetype = type;
6441 klass = mono_class_from_mono_type (type);
6442 if (klass->valuetype) {
6443 object = mono_object_new (domain, klass);
6444 retval = ((gchar *) object + sizeof (MonoObject));
6445 if (klass->enumtype)
6446 basetype = klass->enum_basetype;
6451 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6458 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6462 memset (assembly, 0, sizeof (MonoAssemblyName));
6464 assembly->culture = "";
6465 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6467 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6470 while (g_ascii_isspace (*p) || *p == ',') {
6479 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6481 assembly->major = strtoul (p, &s, 10);
6482 if (s == p || *s != '.')
6485 assembly->minor = strtoul (p, &s, 10);
6486 if (s == p || *s != '.')
6489 assembly->build = strtoul (p, &s, 10);
6490 if (s == p || *s != '.')
6493 assembly->revision = strtoul (p, &s, 10);
6497 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6499 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6500 assembly->culture = "";
6503 assembly->culture = p;
6504 while (*p && *p != ',') {
6508 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6510 if (strncmp (p, "null", 4) == 0) {
6515 while (*p && *p != ',') {
6518 len = (p - start + 1);
6519 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6520 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6521 g_strlcpy ((char*)assembly->public_key_token, start, len);
6524 while (*p && *p != ',')
6528 while (g_ascii_isspace (*p) || *p == ',') {
6542 * mono_reflection_parse_type:
6545 * Parse a type name as accepted by the GetType () method and output the info
6546 * extracted in the info structure.
6547 * the name param will be mangled, so, make a copy before passing it to this function.
6548 * The fields in info will be valid until the memory pointed to by name is valid.
6550 * See also mono_type_get_name () below.
6552 * Returns: 0 on parse error.
6555 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6556 MonoTypeNameParse *info)
6558 char *start, *p, *w, *temp, *last_point, *startn;
6559 int in_modifiers = 0;
6560 int isbyref = 0, rank, arity = 0, i;
6562 start = p = w = name;
6564 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6565 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6566 info->name = info->name_space = NULL;
6567 info->nested = NULL;
6568 info->modifiers = NULL;
6569 info->type_arguments = NULL;
6571 /* last_point separates the namespace from the name */
6577 *p = 0; /* NULL terminate the name */
6579 info->nested = g_list_append (info->nested, startn);
6580 /* we have parsed the nesting namespace + name */
6584 info->name_space = start;
6586 info->name = last_point + 1;
6588 info->name_space = (char *)"";
6607 i = strtol (p, &temp, 10);
6624 info->name_space = start;
6626 info->name = last_point + 1;
6628 info->name_space = (char *)"";
6635 if (isbyref) /* only one level allowed by the spec */
6638 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6642 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6648 info->type_arguments = g_ptr_array_new ();
6649 for (i = 0; i < arity; i++) {
6650 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6651 gboolean fqname = FALSE;
6653 g_ptr_array_add (info->type_arguments, subinfo);
6660 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6671 while (*p && (*p != ']'))
6679 if (g_ascii_isspace (*aname)) {
6686 !assembly_name_to_aname (&subinfo->assembly, aname))
6690 if (i + 1 < arity) {
6710 else if (*p == '*') /* '*' means unknown lower bound */
6711 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6718 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6729 if (g_ascii_isspace (*p)) {
6736 return 0; /* missing assembly name */
6737 if (!assembly_name_to_aname (&info->assembly, p))
6743 if (info->assembly.name)
6746 // *w = 0; /* terminate class name */
6748 if (!info->name || !*info->name)
6752 /* add other consistency checks */
6757 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6759 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6763 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6765 gboolean type_resolve = FALSE;
6767 MonoImage *rootimage = image;
6769 if (info->assembly.name) {
6770 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6772 /* then we must load the assembly ourselve - see #60439 */
6773 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6777 image = assembly->image;
6778 } else if (!image) {
6779 image = mono_defaults.corlib;
6782 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6783 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6784 image = mono_defaults.corlib;
6785 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6792 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6797 gboolean bounded = FALSE;
6800 image = mono_defaults.corlib;
6803 klass = mono_class_from_name_case (image, info->name_space, info->name);
6805 klass = mono_class_from_name (image, info->name_space, info->name);
6808 for (mod = info->nested; mod; mod = mod->next) {
6809 gpointer iter = NULL;
6813 mono_class_init (parent);
6815 while ((klass = mono_class_get_nested_types (parent, &iter))) {
6817 if (g_strcasecmp (klass->name, mod->data) == 0)
6820 if (strcmp (klass->name, mod->data) == 0)
6829 mono_class_init (klass);
6831 if (info->type_arguments) {
6832 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6833 MonoReflectionType *the_type;
6837 for (i = 0; i < info->type_arguments->len; i++) {
6838 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6840 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
6841 if (!type_args [i]) {
6847 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6849 instance = mono_reflection_bind_generic_parameters (
6850 the_type, info->type_arguments->len, type_args);
6856 klass = mono_class_from_mono_type (instance);
6859 for (mod = info->modifiers; mod; mod = mod->next) {
6860 modval = GPOINTER_TO_UINT (mod->data);
6861 if (!modval) { /* byref: must be last modifier */
6862 return &klass->this_arg;
6863 } else if (modval == -1) {
6864 klass = mono_ptr_class_get (&klass->byval_arg);
6865 } else if (modval == -2) {
6867 } else { /* array rank */
6868 klass = mono_bounded_array_class_get (klass, modval, bounded);
6870 mono_class_init (klass);
6873 return &klass->byval_arg;
6877 * mono_reflection_get_type:
6878 * @image: a metadata context
6879 * @info: type description structure
6880 * @ignorecase: flag for case-insensitive string compares
6881 * @type_resolve: whenever type resolve was already tried
6883 * Build a MonoType from the type description in @info.
6888 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
6889 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
6893 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
6895 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
6899 g_assert (assembly->dynamic);
6901 /* Enumerate all modules */
6904 if (abuilder->modules) {
6905 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6906 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6907 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
6913 if (!type && abuilder->loaded_modules) {
6914 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6915 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6916 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
6926 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6929 MonoReflectionAssembly *assembly;
6933 if (image && image->dynamic)
6934 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
6936 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
6939 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6946 *type_resolve = TRUE;
6949 /* Reconstruct the type name */
6950 fullName = g_string_new ("");
6951 if (info->name_space && (info->name_space [0] != '\0'))
6952 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6954 g_string_printf (fullName, info->name);
6955 for (mod = info->nested; mod; mod = mod->next)
6956 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6958 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6960 if (assembly->assembly->dynamic)
6961 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
6963 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
6966 g_string_free (fullName, TRUE);
6971 mono_reflection_free_type_info (MonoTypeNameParse *info)
6973 g_list_free (info->modifiers);
6974 g_list_free (info->nested);
6976 if (info->type_arguments) {
6979 for (i = 0; i < info->type_arguments->len; i++) {
6980 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6982 mono_reflection_free_type_info (subinfo);
6983 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
6987 g_ptr_array_free (info->type_arguments, TRUE);
6992 * mono_reflection_type_from_name:
6994 * @image: a metadata context (can be NULL).
6996 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6997 * it defaults to get the type from @image or, if @image is NULL or loading
6998 * from it fails, uses corlib.
7002 mono_reflection_type_from_name (char *name, MonoImage *image)
7004 MonoType *type = NULL;
7005 MonoTypeNameParse info;
7008 /* Make a copy since parse_type modifies its argument */
7009 tmp = g_strdup (name);
7011 /*g_print ("requested type %s\n", str);*/
7012 if (mono_reflection_parse_type (tmp, &info)) {
7013 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7017 mono_reflection_free_type_info (&info);
7022 * mono_reflection_get_token:
7024 * Return the metadata token of OBJ which should be an object
7025 * representing a metadata element.
7028 mono_reflection_get_token (MonoObject *obj)
7033 klass = obj->vtable->klass;
7035 if (strcmp (klass->name, "MethodBuilder") == 0) {
7036 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7038 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7039 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7040 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7042 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7043 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7044 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7046 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7047 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7048 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7049 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7050 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7051 } else if (strcmp (klass->name, "MonoType") == 0) {
7052 MonoReflectionType *tb = (MonoReflectionType *)obj;
7053 token = mono_class_from_mono_type (tb->type)->type_token;
7054 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7055 strcmp (klass->name, "MonoMethod") == 0 ||
7056 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7057 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7058 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7059 if (m->method->is_inflated) {
7060 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7061 return inflated->declaring->token;
7063 token = m->method->token;
7065 } else if (strcmp (klass->name, "MonoField") == 0) {
7066 MonoReflectionField *f = (MonoReflectionField*)obj;
7068 if (f->field->generic_info && f->field->generic_info->reflection_info)
7069 return mono_reflection_get_token (f->field->generic_info->reflection_info);
7071 token = mono_class_get_field_token (f->field);
7072 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7073 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7075 token = mono_class_get_property_token (p->property);
7076 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7077 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7079 token = mono_class_get_event_token (p->event);
7080 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7081 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7083 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7084 } else if (strcmp (klass->name, "Module") == 0) {
7085 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7088 } else if (strcmp (klass->name, "Assembly") == 0) {
7089 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7091 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7092 MonoException *ex = mono_get_exception_not_implemented (msg);
7094 mono_raise_exception (ex);
7101 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7103 int slen, type = t->type;
7104 MonoClass *tklass = t->data.klass;
7110 case MONO_TYPE_BOOLEAN: {
7111 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7116 case MONO_TYPE_CHAR:
7118 case MONO_TYPE_I2: {
7119 guint16 *val = g_malloc (sizeof (guint16));
7124 #if SIZEOF_VOID_P == 4
7130 case MONO_TYPE_I4: {
7131 guint32 *val = g_malloc (sizeof (guint32));
7136 #if SIZEOF_VOID_P == 8
7137 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7141 case MONO_TYPE_I8: {
7142 guint64 *val = g_malloc (sizeof (guint64));
7147 case MONO_TYPE_R8: {
7148 double *val = g_malloc (sizeof (double));
7153 case MONO_TYPE_VALUETYPE:
7154 if (t->data.klass->enumtype) {
7155 type = t->data.klass->enum_basetype->type;
7158 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7161 case MONO_TYPE_STRING:
7162 if (*p == (char)0xFF) {
7166 slen = mono_metadata_decode_value (p, &p);
7168 return mono_string_new_len (mono_domain_get (), p, slen);
7169 case MONO_TYPE_CLASS: {
7172 if (*p == (char)0xFF) {
7177 slen = mono_metadata_decode_value (p, &p);
7178 n = g_memdup (p, slen + 1);
7180 t = mono_reflection_type_from_name (n, image);
7182 g_warning ("Cannot load type '%s'", n);
7186 return mono_type_get_object (mono_domain_get (), t);
7190 case MONO_TYPE_OBJECT: {
7193 MonoClass *subc = NULL;
7198 } else if (subt == 0x0E) {
7199 type = MONO_TYPE_STRING;
7201 } else if (subt == 0x1D) {
7202 MonoType simple_type = {{0}};
7207 /* See Partition II, Appendix B3 */
7208 etype = MONO_TYPE_OBJECT;
7209 type = MONO_TYPE_SZARRAY;
7210 simple_type.type = etype;
7211 tklass = mono_class_from_mono_type (&simple_type);
7213 } else if (subt == 0x55) {
7216 slen = mono_metadata_decode_value (p, &p);
7217 n = g_memdup (p, slen + 1);
7219 t = mono_reflection_type_from_name (n, image);
7221 g_error ("Cannot load type '%s'", n);
7224 subc = mono_class_from_mono_type (t);
7225 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7226 MonoType simple_type = {{0}};
7227 simple_type.type = subt;
7228 subc = mono_class_from_mono_type (&simple_type);
7230 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7232 val = load_cattr_value (image, &subc->byval_arg, p, end);
7233 obj = mono_object_new (mono_domain_get (), subc);
7234 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7238 case MONO_TYPE_SZARRAY: {
7240 guint32 i, alen, basetype;
7243 if (alen == 0xffffffff) {
7247 arr = mono_array_new (mono_domain_get(), tklass, alen);
7248 basetype = tklass->byval_arg.type;
7249 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7250 basetype = tklass->enum_basetype->type;
7255 case MONO_TYPE_BOOLEAN:
7256 for (i = 0; i < alen; i++) {
7257 MonoBoolean val = *p++;
7258 mono_array_set (arr, MonoBoolean, i, val);
7261 case MONO_TYPE_CHAR:
7264 for (i = 0; i < alen; i++) {
7265 guint16 val = read16 (p);
7266 mono_array_set (arr, guint16, i, val);
7273 for (i = 0; i < alen; i++) {
7274 guint32 val = read32 (p);
7275 mono_array_set (arr, guint32, i, val);
7280 for (i = 0; i < alen; i++) {
7283 mono_array_set (arr, double, i, val);
7289 for (i = 0; i < alen; i++) {
7290 guint64 val = read64 (p);
7291 mono_array_set (arr, guint64, i, val);
7295 case MONO_TYPE_CLASS:
7296 case MONO_TYPE_OBJECT:
7297 case MONO_TYPE_STRING:
7298 for (i = 0; i < alen; i++) {
7299 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7300 mono_array_setref (arr, i, item);
7304 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7310 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7316 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7318 static MonoClass *klass;
7319 static MonoMethod *ctor;
7321 void *params [2], *unboxed;
7324 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7326 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7328 params [0] = mono_type_get_object (mono_domain_get (), t);
7330 retval = mono_object_new (mono_domain_get (), klass);
7331 unboxed = mono_object_unbox (retval);
7332 mono_runtime_invoke (ctor, unboxed, params, NULL);
7338 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7340 static MonoClass *klass;
7341 static MonoMethod *ctor;
7343 void *unboxed, *params [2];
7346 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7348 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7351 params [1] = typedarg;
7352 retval = mono_object_new (mono_domain_get (), klass);
7353 unboxed = mono_object_unbox (retval);
7354 mono_runtime_invoke (ctor, unboxed, params, NULL);
7360 type_is_reference (MonoType *type)
7362 switch (type->type) {
7363 case MONO_TYPE_BOOLEAN:
7364 case MONO_TYPE_CHAR:
7377 case MONO_TYPE_VALUETYPE:
7385 free_param_data (MonoMethodSignature *sig, void **params) {
7387 for (i = 0; i < sig->param_count; ++i) {
7388 if (!type_is_reference (sig->params [i]))
7389 g_free (params [i]);
7394 * Find the field index in the metadata FieldDef table.
7397 find_field_index (MonoClass *klass, MonoClassField *field) {
7400 for (i = 0; i < klass->field.count; ++i) {
7401 if (field == &klass->fields [i])
7402 return klass->field.first + 1 + i;
7408 * Find the property index in the metadata Property table.
7411 find_property_index (MonoClass *klass, MonoProperty *property) {
7414 for (i = 0; i < klass->property.count; ++i) {
7415 if (property == &klass->properties [i])
7416 return klass->property.first + 1 + i;
7422 * Find the event index in the metadata Event table.
7425 find_event_index (MonoClass *klass, MonoEvent *event) {
7428 for (i = 0; i < klass->event.count; ++i) {
7429 if (event == &klass->events [i])
7430 return klass->event.first + 1 + i;
7436 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7438 const char *p = (const char*)data;
7440 guint32 i, j, num_named;
7444 mono_class_init (method->klass);
7447 attr = mono_object_new (mono_domain_get (), method->klass);
7448 mono_runtime_invoke (method, attr, NULL, NULL);
7452 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7455 /*g_print ("got attr %s\n", method->klass->name);*/
7457 /* Allocate using alloca so it gets GC tracking */
7458 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7462 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7463 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7467 attr = mono_object_new (mono_domain_get (), method->klass);
7468 mono_runtime_invoke (method, attr, params, NULL);
7469 free_param_data (method->signature, params);
7470 num_named = read16 (named);
7472 for (j = 0; j < num_named; j++) {
7474 char *name, named_type, data_type;
7475 named_type = *named++;
7476 data_type = *named++; /* type of data */
7477 if (data_type == MONO_TYPE_SZARRAY)
7478 data_type = *named++;
7479 if (data_type == MONO_TYPE_ENUM) {
7482 type_len = mono_metadata_decode_blob_size (named, &named);
7483 type_name = g_malloc (type_len + 1);
7484 memcpy (type_name, named, type_len);
7485 type_name [type_len] = 0;
7487 /* FIXME: lookup the type and check type consistency */
7490 name_len = mono_metadata_decode_blob_size (named, &named);
7491 name = g_malloc (name_len + 1);
7492 memcpy (name, named, name_len);
7493 name [name_len] = 0;
7495 if (named_type == 0x53) {
7496 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7497 void *val = load_cattr_value (image, field->type, named, &named);
7498 mono_field_set_value (attr, field, val);
7499 if (!type_is_reference (field->type))
7501 } else if (named_type == 0x54) {
7504 MonoType *prop_type;
7506 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7507 /* can we have more that 1 arg in a custom attr named property? */
7508 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7509 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7510 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7511 mono_property_set_value (prop, attr, pparams, NULL);
7512 if (!type_is_reference (prop_type))
7513 g_free (pparams [0]);
7522 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7524 MonoArray *typedargs, *namedargs;
7525 MonoClass *attrklass;
7526 static MonoMethod *ctor;
7529 const char *p = (const char*)data;
7531 guint32 i, j, num_named;
7534 mono_class_init (method->klass);
7537 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7539 domain = mono_domain_get ();
7541 /* This is for Attributes with no parameters */
7542 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7543 params [0] = mono_method_get_object (domain, method, NULL);
7544 params [1] = params [2] = NULL;
7545 mono_runtime_invoke (method, attr, params, NULL);
7549 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7552 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7556 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7557 MonoObject *obj, *typedarg;
7560 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7561 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7562 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7563 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7564 mono_array_setref (typedargs, i, typedarg);
7566 if (!type_is_reference (mono_method_signature (method)->params [i]))
7571 num_named = read16 (named);
7572 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7574 attrklass = method->klass;
7575 for (j = 0; j < num_named; j++) {
7577 char *name, named_type, data_type;
7578 named_type = *named++;
7579 data_type = *named++; /* type of data */
7580 if (data_type == MONO_TYPE_SZARRAY)
7581 data_type = *named++;
7582 if (data_type == MONO_TYPE_ENUM) {
7585 type_len = mono_metadata_decode_blob_size (named, &named);
7586 type_name = g_malloc (type_len + 1);
7587 memcpy (type_name, named, type_len);
7588 type_name [type_len] = 0;
7590 /* FIXME: lookup the type and check type consistency */
7593 name_len = mono_metadata_decode_blob_size (named, &named);
7594 name = g_malloc (name_len + 1);
7595 memcpy (name, named, name_len);
7596 name [name_len] = 0;
7598 if (named_type == 0x53) {
7599 MonoObject *obj, *typedarg, *namedarg;
7600 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7601 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7603 minfo = mono_field_get_object (domain, NULL, field);
7604 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7605 typedarg = create_cattr_typed_arg (field->type, obj);
7606 namedarg = create_cattr_named_arg (minfo, typedarg);
7607 mono_array_setref (namedargs, j, namedarg);
7608 if (!type_is_reference (field->type))
7610 } else if (named_type == 0x54) {
7611 MonoObject *obj, *typedarg, *namedarg;
7612 MonoType *prop_type;
7614 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7616 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7617 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7618 minfo = mono_property_get_object (domain, NULL, prop);
7619 val = load_cattr_value (image, prop_type, named, &named);
7620 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7621 typedarg = create_cattr_typed_arg (prop_type, obj);
7622 namedarg = create_cattr_named_arg (minfo, typedarg);
7623 mono_array_setref (namedargs, j, namedarg);
7624 if (!type_is_reference (prop_type))
7629 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7630 params [0] = mono_method_get_object (domain, method, NULL);
7631 params [1] = typedargs;
7632 params [2] = namedargs;
7633 mono_runtime_invoke (ctor, attr, params, NULL);
7638 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7644 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7645 for (i = 0; i < cinfo->num_attrs; ++i) {
7646 if (!cinfo->attrs [i].ctor)
7647 /* The cattr type is not finished yet */
7648 /* We should include the type name but cinfo doesn't contain it */
7649 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7650 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7651 mono_array_setref (result, i, attr);
7657 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7664 for (i = 0; i < cinfo->num_attrs; ++i) {
7665 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7669 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7671 for (i = 0; i < cinfo->num_attrs; ++i) {
7672 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7673 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7674 mono_array_setref (result, n, attr);
7682 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7688 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7689 for (i = 0; i < cinfo->num_attrs; ++i) {
7690 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7691 mono_array_setref (result, i, attr);
7697 * mono_custom_attrs_from_index:
7699 * Returns: NULL if no attributes are found or if a loading error occurs.
7702 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7704 guint32 mtoken, i, len;
7705 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7707 MonoCustomAttrInfo *ainfo;
7708 GList *tmp, *list = NULL;
7711 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7713 i = mono_metadata_custom_attrs_from_index (image, idx);
7717 while (i < ca->rows) {
7718 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7720 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7723 len = g_list_length (list);
7726 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7727 ainfo->num_attrs = len;
7728 ainfo->image = image;
7729 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7730 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7731 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7732 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7733 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7734 mtoken |= MONO_TOKEN_METHOD_DEF;
7736 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7737 mtoken |= MONO_TOKEN_MEMBER_REF;
7740 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7743 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7744 if (!ainfo->attrs [i].ctor) {
7745 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7750 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7751 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7752 ainfo->attrs [i].data = (guchar*)data;
7760 mono_custom_attrs_from_method (MonoMethod *method)
7765 * An instantiated method has the same cattrs as the generic method definition.
7767 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7768 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7770 if (method->is_inflated)
7771 method = ((MonoMethodInflated *) method)->declaring;
7773 if (method->dynamic || method->klass->image->dynamic)
7774 return lookup_custom_attr (method->klass->image, method);
7776 idx = mono_method_get_index (method);
7777 idx <<= MONO_CUSTOM_ATTR_BITS;
7778 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7779 return mono_custom_attrs_from_index (method->klass->image, idx);
7783 mono_custom_attrs_from_class (MonoClass *klass)
7787 if (klass->generic_class)
7788 klass = klass->generic_class->container_class;
7790 if (klass->image->dynamic)
7791 return lookup_custom_attr (klass->image, klass);
7793 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
7794 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
7795 idx <<= MONO_CUSTOM_ATTR_BITS;
7796 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
7798 idx = mono_metadata_token_index (klass->type_token);
7799 idx <<= MONO_CUSTOM_ATTR_BITS;
7800 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7802 return mono_custom_attrs_from_index (klass->image, idx);
7806 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7810 if (assembly->image->dynamic)
7811 return lookup_custom_attr (assembly->image, assembly);
7812 idx = 1; /* there is only one assembly */
7813 idx <<= MONO_CUSTOM_ATTR_BITS;
7814 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7815 return mono_custom_attrs_from_index (assembly->image, idx);
7818 static MonoCustomAttrInfo*
7819 mono_custom_attrs_from_module (MonoImage *image)
7824 return lookup_custom_attr (image, image);
7825 idx = 1; /* there is only one module */
7826 idx <<= MONO_CUSTOM_ATTR_BITS;
7827 idx |= MONO_CUSTOM_ATTR_MODULE;
7828 return mono_custom_attrs_from_index (image, idx);
7832 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7836 if (klass->image->dynamic) {
7837 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
7838 return lookup_custom_attr (klass->image, property);
7840 idx = find_property_index (klass, property);
7841 idx <<= MONO_CUSTOM_ATTR_BITS;
7842 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7843 return mono_custom_attrs_from_index (klass->image, idx);
7847 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7851 if (klass->image->dynamic) {
7852 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
7853 return lookup_custom_attr (klass->image, event);
7855 idx = find_event_index (klass, event);
7856 idx <<= MONO_CUSTOM_ATTR_BITS;
7857 idx |= MONO_CUSTOM_ATTR_EVENT;
7858 return mono_custom_attrs_from_index (klass->image, idx);
7862 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7865 if (klass->image->dynamic) {
7866 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
7867 return lookup_custom_attr (klass->image, field);
7869 idx = find_field_index (klass, field);
7870 idx <<= MONO_CUSTOM_ATTR_BITS;
7871 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7872 return mono_custom_attrs_from_index (klass->image, idx);
7876 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7879 guint32 i, idx, method_index;
7880 guint32 param_list, param_last, param_pos, found;
7882 MonoReflectionMethodAux *aux;
7885 * An instantiated method has the same cattrs as the generic method definition.
7887 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7888 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7890 if (method->is_inflated)
7891 method = ((MonoMethodInflated *) method)->declaring;
7893 if (method->klass->image->dynamic) {
7894 MonoCustomAttrInfo *res, *ainfo;
7897 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7898 if (!aux || !aux->param_cattr)
7901 /* Need to copy since it will be freed later */
7902 ainfo = aux->param_cattr [param];
7903 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7904 res = g_malloc0 (size);
7905 memcpy (res, ainfo, size);
7909 image = method->klass->image;
7910 method_index = mono_method_get_index (method);
7911 ca = &image->tables [MONO_TABLE_METHOD];
7913 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7914 if (method_index == ca->rows) {
7915 ca = &image->tables [MONO_TABLE_PARAM];
7916 param_last = ca->rows + 1;
7918 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7919 ca = &image->tables [MONO_TABLE_PARAM];
7922 for (i = param_list; i < param_last; ++i) {
7923 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7924 if (param_pos == param) {
7932 idx <<= MONO_CUSTOM_ATTR_BITS;
7933 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7934 return mono_custom_attrs_from_index (image, idx);
7938 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7942 for (i = 0; i < ainfo->num_attrs; ++i) {
7943 klass = ainfo->attrs [i].ctor->klass;
7944 if (mono_class_has_parent (klass, attr_klass))
7951 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7958 for (i = 0; i < ainfo->num_attrs; ++i) {
7959 klass = ainfo->attrs [i].ctor->klass;
7960 if (mono_class_has_parent (klass, attr_klass)) {
7965 if (attr_index == -1)
7968 attrs = mono_custom_attrs_construct (ainfo);
7970 return mono_array_get (attrs, MonoObject*, attr_index);
7976 * mono_reflection_get_custom_attrs_info:
7977 * @obj: a reflection object handle
7979 * Return the custom attribute info for attributes defined for the
7980 * reflection handle @obj. The objects.
7983 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7986 MonoCustomAttrInfo *cinfo = NULL;
7988 klass = obj->vtable->klass;
7989 if (klass == mono_defaults.monotype_class) {
7990 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7991 klass = mono_class_from_mono_type (rtype->type);
7992 cinfo = mono_custom_attrs_from_class (klass);
7993 } else if (strcmp ("Assembly", klass->name) == 0) {
7994 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7995 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7996 } else if (strcmp ("Module", klass->name) == 0) {
7997 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7998 cinfo = mono_custom_attrs_from_module (module->image);
7999 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8000 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8001 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8002 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8003 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
8004 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8005 } else if (strcmp ("MonoField", klass->name) == 0) {
8006 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8007 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8008 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8009 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8010 cinfo = mono_custom_attrs_from_method (rmethod->method);
8011 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8012 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8013 cinfo = mono_custom_attrs_from_method (rmethod->method);
8014 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8015 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8016 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8017 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8018 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8019 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8020 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8021 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8022 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8023 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8024 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8025 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8026 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8027 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8028 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8029 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8030 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8031 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8032 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8033 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8034 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8035 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8036 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8037 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8038 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8039 } else { /* handle other types here... */
8040 g_error ("get custom attrs not yet supported for %s", klass->name);
8047 * mono_reflection_get_custom_attrs_by_type:
8048 * @obj: a reflection object handle
8050 * Return an array with all the custom attributes defined of the
8051 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8052 * of that type are returned. The objects are fully build. Return NULL if a loading error
8056 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8059 MonoCustomAttrInfo *cinfo;
8061 cinfo = mono_reflection_get_custom_attrs_info (obj);
8064 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8066 result = mono_custom_attrs_construct (cinfo);
8068 mono_custom_attrs_free (cinfo);
8070 if (mono_loader_get_last_error ())
8072 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8079 * mono_reflection_get_custom_attrs:
8080 * @obj: a reflection object handle
8082 * Return an array with all the custom attributes defined of the
8083 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8087 mono_reflection_get_custom_attrs (MonoObject *obj)
8089 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8093 * mono_reflection_get_custom_attrs_data:
8094 * @obj: a reflection obj handle
8096 * Returns an array of System.Reflection.CustomAttributeData,
8097 * which include information about attributes reflected on
8098 * types loaded using the Reflection Only methods
8101 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8104 MonoCustomAttrInfo *cinfo;
8106 cinfo = mono_reflection_get_custom_attrs_info (obj);
8108 result = mono_custom_attrs_data_construct (cinfo);
8110 mono_custom_attrs_free (cinfo);
8112 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8117 static MonoReflectionType*
8118 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8120 MonoMethod *method_get_underlying_system_type;
8122 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8123 mono_class_get_method_from_name (mono_object_class (t),
8124 "get_UnderlyingSystemType",
8126 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8130 mono_reflection_type_get_handle (MonoReflectionType* t)
8135 t = mono_reflection_type_get_underlying_system_type (t);
8143 * LOCKING: Assumes the loader lock is held.
8145 static MonoMethodSignature*
8146 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
8147 MonoMethodSignature *sig;
8150 count = parameters? mono_array_length (parameters): 0;
8152 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8153 sig->param_count = count;
8154 sig->sentinelpos = -1; /* FIXME */
8155 for (i = 0; i < count; ++i) {
8156 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8157 sig->params [i] = mono_reflection_type_get_handle (pt);
8163 * LOCKING: Assumes the loader lock is held.
8165 static MonoMethodSignature*
8166 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
8167 MonoMethodSignature *sig;
8169 sig = parameters_to_signature (mp, ctor->parameters);
8170 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8171 sig->ret = &mono_defaults.void_class->byval_arg;
8176 * LOCKING: Assumes the loader lock is held.
8178 static MonoMethodSignature*
8179 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
8180 MonoMethodSignature *sig;
8182 sig = parameters_to_signature (mp, method->parameters);
8183 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8184 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8185 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8189 static MonoMethodSignature*
8190 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8191 MonoMethodSignature *sig;
8193 sig = parameters_to_signature (NULL, method->parameters);
8194 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8195 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8196 sig->generic_param_count = 0;
8201 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8203 MonoClass *klass = mono_object_class (prop);
8204 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8205 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8206 *name = mono_string_to_utf8 (pb->name);
8207 *type = pb->type->type;
8209 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8210 *name = g_strdup (p->property->name);
8211 if (p->property->get)
8212 *type = mono_method_signature (p->property->get)->ret;
8214 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8219 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8221 MonoClass *klass = mono_object_class (field);
8222 if (strcmp (klass->name, "FieldBuilder") == 0) {
8223 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8224 *name = mono_string_to_utf8 (fb->name);
8225 *type = fb->type->type;
8227 MonoReflectionField *f = (MonoReflectionField *)field;
8228 *name = g_strdup (f->field->name);
8229 *type = f->field->type;
8234 * Encode a value in a custom attribute stream of bytes.
8235 * The value to encode is either supplied as an object in argument val
8236 * (valuetypes are boxed), or as a pointer to the data in the
8238 * @type represents the type of the value
8239 * @buffer is the start of the buffer
8240 * @p the current position in the buffer
8241 * @buflen contains the size of the buffer and is used to return the new buffer size
8242 * if this needs to be realloced.
8243 * @retbuffer and @retp return the start and the position of the buffer
8246 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8248 MonoTypeEnum simple_type;
8250 if ((p-buffer) + 10 >= *buflen) {
8253 newbuf = g_realloc (buffer, *buflen);
8254 p = newbuf + (p-buffer);
8258 argval = ((char*)arg + sizeof (MonoObject));
8259 simple_type = type->type;
8261 switch (simple_type) {
8262 case MONO_TYPE_BOOLEAN:
8267 case MONO_TYPE_CHAR:
8270 swap_with_size (p, argval, 2, 1);
8276 swap_with_size (p, argval, 4, 1);
8280 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8290 swap_with_size (p, argval, 8, 1);
8296 swap_with_size (p, argval, 8, 1);
8299 case MONO_TYPE_VALUETYPE:
8300 if (type->data.klass->enumtype) {
8301 simple_type = type->data.klass->enum_basetype->type;
8304 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8307 case MONO_TYPE_STRING: {
8314 str = mono_string_to_utf8 ((MonoString*)arg);
8315 slen = strlen (str);
8316 if ((p-buffer) + 10 + slen >= *buflen) {
8320 newbuf = g_realloc (buffer, *buflen);
8321 p = newbuf + (p-buffer);
8324 mono_metadata_encode_value (slen, p, &p);
8325 memcpy (p, str, slen);
8330 case MONO_TYPE_CLASS: {
8338 k = mono_object_class (arg);
8339 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8340 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8341 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8344 if (rt && (rtc = mono_object_class (rt)) &&
8345 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8346 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8347 arg = (MonoObject *) rt;
8350 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8353 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8354 slen = strlen (str);
8355 if ((p-buffer) + 10 + slen >= *buflen) {
8359 newbuf = g_realloc (buffer, *buflen);
8360 p = newbuf + (p-buffer);
8363 mono_metadata_encode_value (slen, p, &p);
8364 memcpy (p, str, slen);
8369 case MONO_TYPE_SZARRAY: {
8371 MonoClass *eclass, *arg_eclass;
8374 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8377 len = mono_array_length ((MonoArray*)arg);
8379 *p++ = (len >> 8) & 0xff;
8380 *p++ = (len >> 16) & 0xff;
8381 *p++ = (len >> 24) & 0xff;
8383 *retbuffer = buffer;
8384 eclass = type->data.klass;
8385 arg_eclass = mono_object_class (arg)->element_class;
8388 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8389 eclass = mono_defaults.object_class;
8391 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8392 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8393 int elsize = mono_class_array_element_size (arg_eclass);
8394 for (i = 0; i < len; ++i) {
8395 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8398 } else if (eclass->valuetype && arg_eclass->valuetype) {
8399 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8400 int elsize = mono_class_array_element_size (eclass);
8401 for (i = 0; i < len; ++i) {
8402 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8406 for (i = 0; i < len; ++i) {
8407 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8412 case MONO_TYPE_OBJECT: {
8418 * The parameter type is 'object' but the type of the actual
8419 * argument is not. So we have to add type information to the blob
8420 * too. This is completely undocumented in the spec.
8424 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8429 klass = mono_object_class (arg);
8431 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8434 } else if (klass->enumtype) {
8436 } else if (klass == mono_defaults.string_class) {
8437 simple_type = MONO_TYPE_STRING;
8440 } else if (klass->rank == 1) {
8442 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8443 /* See Partition II, Appendix B3 */
8446 *p++ = klass->element_class->byval_arg.type;
8447 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8449 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8450 *p++ = simple_type = klass->byval_arg.type;
8453 g_error ("unhandled type in custom attr");
8455 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8456 slen = strlen (str);
8457 if ((p-buffer) + 10 + slen >= *buflen) {
8461 newbuf = g_realloc (buffer, *buflen);
8462 p = newbuf + (p-buffer);
8465 mono_metadata_encode_value (slen, p, &p);
8466 memcpy (p, str, slen);
8469 simple_type = klass->enum_basetype->type;
8473 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8476 *retbuffer = buffer;
8480 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8482 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8483 char *str = type_get_qualified_name (type, NULL);
8484 int slen = strlen (str);
8488 * This seems to be optional...
8491 mono_metadata_encode_value (slen, p, &p);
8492 memcpy (p, str, slen);
8495 } else if (type->type == MONO_TYPE_OBJECT) {
8497 } else if (type->type == MONO_TYPE_CLASS) {
8498 /* it should be a type: encode_cattr_value () has the check */
8501 mono_metadata_encode_value (type->type, p, &p);
8502 if (type->type == MONO_TYPE_SZARRAY)
8503 /* See the examples in Partition VI, Annex B */
8504 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8511 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8514 /* Preallocate a large enough buffer */
8515 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8516 char *str = type_get_qualified_name (type, NULL);
8519 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8520 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8526 len += strlen (name);
8528 if ((p-buffer) + 20 + len >= *buflen) {
8532 newbuf = g_realloc (buffer, *buflen);
8533 p = newbuf + (p-buffer);
8537 encode_field_or_prop_type (type, p, &p);
8539 len = strlen (name);
8540 mono_metadata_encode_value (len, p, &p);
8541 memcpy (p, name, len);
8543 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8545 *retbuffer = buffer;
8549 * mono_reflection_get_custom_attrs_blob:
8550 * @ctor: custom attribute constructor
8551 * @ctorArgs: arguments o the constructor
8557 * Creates the blob of data that needs to be saved in the metadata and that represents
8558 * the custom attributed described by @ctor, @ctorArgs etc.
8559 * Returns: a Byte array representing the blob of data.
8562 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8565 MonoMethodSignature *sig;
8570 MONO_ARCH_SAVE_REGS;
8572 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8573 /* sig is freed later so allocate it in the heap */
8574 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8576 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8579 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8581 p = buffer = g_malloc (buflen);
8582 /* write the prolog */
8585 for (i = 0; i < sig->param_count; ++i) {
8586 arg = mono_array_get (ctorArgs, MonoObject*, i);
8587 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8591 i += mono_array_length (properties);
8593 i += mono_array_length (fields);
8595 *p++ = (i >> 8) & 0xff;
8598 for (i = 0; i < mono_array_length (properties); ++i) {
8602 prop = mono_array_get (properties, gpointer, i);
8603 get_prop_name_and_type (prop, &pname, &ptype);
8604 *p++ = 0x54; /* PROPERTY signature */
8605 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8612 for (i = 0; i < mono_array_length (fields); ++i) {
8616 field = mono_array_get (fields, gpointer, i);
8617 get_field_name_and_type (field, &fname, &ftype);
8618 *p++ = 0x53; /* FIELD signature */
8619 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8624 g_assert (p - buffer <= buflen);
8625 buflen = p - buffer;
8626 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8627 p = mono_array_addr (result, char, 0);
8628 memcpy (p, buffer, buflen);
8630 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8636 static void* reflection_info_desc = NULL;
8637 #define MOVING_GC_REGISTER(addr) do { \
8638 if (!reflection_info_desc) { \
8640 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8642 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8645 #define MOVING_GC_REGISTER(addr)
8649 * mono_reflection_setup_internal_class:
8650 * @tb: a TypeBuilder object
8652 * Creates a MonoClass that represents the TypeBuilder.
8653 * This is a trick that lets us simplify a lot of reflection code
8654 * (and will allow us to support Build and Run assemblies easier).
8657 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8659 MonoClass *klass, *parent;
8661 MONO_ARCH_SAVE_REGS;
8663 mono_loader_lock ();
8666 /* check so we can compile corlib correctly */
8667 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8668 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8669 parent = tb->parent->type->data.klass;
8671 parent = my_mono_class_from_mono_type (tb->parent->type);
8677 /* the type has already being created: it means we just have to change the parent */
8678 if (tb->type.type) {
8679 klass = mono_class_from_mono_type (tb->type.type);
8680 klass->parent = NULL;
8681 /* fool mono_class_setup_parent */
8682 klass->supertypes = NULL;
8683 mono_class_setup_parent (klass, parent);
8684 mono_class_setup_mono_type (klass);
8685 mono_loader_unlock ();
8689 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8691 klass->image = &tb->module->dynamic_image->image;
8693 klass->inited = 1; /* we lie to the runtime */
8694 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8695 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8696 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8697 klass->flags = tb->attrs;
8699 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8701 klass->element_class = klass;
8703 MOVING_GC_REGISTER (&klass->reflection_info);
8704 klass->reflection_info = tb;
8706 /* Put into cache so mono_class_get () will find it */
8707 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8709 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8710 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8712 if (parent != NULL) {
8713 mono_class_setup_parent (klass, parent);
8714 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8715 const char *old_n = klass->name;
8716 /* trick to get relative numbering right when compiling corlib */
8717 klass->name = "BuildingObject";
8718 mono_class_setup_parent (klass, mono_defaults.object_class);
8719 klass->name = old_n;
8722 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8723 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8724 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8725 klass->instance_size = sizeof (MonoObject);
8726 klass->size_inited = 1;
8727 mono_class_setup_vtable_general (klass, NULL, 0);
8730 mono_class_setup_mono_type (klass);
8732 mono_class_setup_supertypes (klass);
8735 * FIXME: handle interfaces.
8738 tb->type.type = &klass->byval_arg;
8740 if (tb->nesting_type) {
8741 g_assert (tb->nesting_type->type);
8742 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8745 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8747 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8749 mono_loader_unlock ();
8753 * mono_reflection_setup_generic_class:
8754 * @tb: a TypeBuilder object
8756 * Setup the generic class before adding the first generic parameter.
8759 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8763 MONO_ARCH_SAVE_REGS;
8765 klass = my_mono_class_from_mono_type (tb->type.type);
8766 if (tb->generic_container)
8769 tb->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
8770 tb->generic_container->owner.klass = klass;
8774 * mono_reflection_create_generic_class:
8775 * @tb: a TypeBuilder object
8777 * Creates the generic class after all generic parameters have been added.
8780 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8785 MONO_ARCH_SAVE_REGS;
8787 klass = my_mono_class_from_mono_type (tb->type.type);
8789 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8791 if (klass->generic_container || (count == 0))
8794 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8796 klass->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
8798 klass->generic_container->owner.klass = klass;
8799 klass->generic_container->type_argc = count;
8800 klass->generic_container->type_params = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericParam) * count);
8802 for (i = 0; i < count; i++) {
8803 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8804 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8805 /*Make sure we are a diferent type instance */
8806 klass->generic_container->type_params [i].owner = klass->generic_container;
8807 klass->generic_container->type_params [i].pklass = NULL;
8809 g_assert (klass->generic_container->type_params [i].owner);
8812 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8816 * mono_reflection_create_internal_class:
8817 * @tb: a TypeBuilder object
8819 * Actually create the MonoClass that is associated with the TypeBuilder.
8822 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8826 MONO_ARCH_SAVE_REGS;
8828 klass = my_mono_class_from_mono_type (tb->type.type);
8830 mono_loader_lock ();
8831 if (klass->enumtype && klass->enum_basetype == NULL) {
8832 MonoReflectionFieldBuilder *fb;
8835 g_assert (tb->fields != NULL);
8836 g_assert (mono_array_length (tb->fields) >= 1);
8838 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8840 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8841 mono_loader_unlock ();
8845 klass->enum_basetype = fb->type->type;
8846 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8847 if (!klass->element_class)
8848 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8851 * get the element_class from the current corlib.
8853 ec = default_class_from_mono_type (klass->enum_basetype);
8854 klass->instance_size = ec->instance_size;
8855 klass->size_inited = 1;
8857 * this is almost safe to do with enums and it's needed to be able
8858 * to create objects of the enum type (for use in SetConstant).
8860 /* FIXME: Does this mean enums can't have method overrides ? */
8861 mono_class_setup_vtable_general (klass, NULL, 0);
8863 mono_loader_unlock ();
8866 static MonoMarshalSpec*
8867 mono_marshal_spec_from_builder (MonoMemPool *mp, MonoAssembly *assembly,
8868 MonoReflectionMarshal *minfo)
8870 MonoMarshalSpec *res;
8872 res = mp_g_new0 (mp, MonoMarshalSpec, 1);
8873 res->native = minfo->type;
8875 switch (minfo->type) {
8876 case MONO_NATIVE_LPARRAY:
8877 res->data.array_data.elem_type = minfo->eltype;
8878 if (minfo->has_size) {
8879 res->data.array_data.param_num = minfo->param_num;
8880 res->data.array_data.num_elem = minfo->count;
8881 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8884 res->data.array_data.param_num = -1;
8885 res->data.array_data.num_elem = -1;
8886 res->data.array_data.elem_mult = -1;
8890 case MONO_NATIVE_BYVALTSTR:
8891 case MONO_NATIVE_BYVALARRAY:
8892 res->data.array_data.num_elem = minfo->count;
8895 case MONO_NATIVE_CUSTOM:
8896 if (minfo->marshaltyperef)
8897 res->data.custom_data.custom_name =
8898 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8900 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8910 MonoReflectionMarshal*
8911 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8912 MonoMarshalSpec *spec)
8914 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8915 MonoReflectionMarshal *minfo;
8918 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8919 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8920 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8921 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8924 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8925 minfo->type = spec->native;
8927 switch (minfo->type) {
8928 case MONO_NATIVE_LPARRAY:
8929 minfo->eltype = spec->data.array_data.elem_type;
8930 minfo->count = spec->data.array_data.num_elem;
8931 minfo->param_num = spec->data.array_data.param_num;
8934 case MONO_NATIVE_BYVALTSTR:
8935 case MONO_NATIVE_BYVALARRAY:
8936 minfo->count = spec->data.array_data.num_elem;
8939 case MONO_NATIVE_CUSTOM:
8940 if (spec->data.custom_data.custom_name) {
8941 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8943 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8945 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8947 if (spec->data.custom_data.cookie)
8948 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8959 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8960 ReflectionMethodBuilder *rmb,
8961 MonoMethodSignature *sig)
8964 MonoMethodNormal *pm;
8965 MonoMarshalSpec **specs;
8966 MonoReflectionMethodAux *method_aux;
8972 * Methods created using a MethodBuilder should have their memory allocated
8973 * inside the image mempool, while dynamic methods should have their memory
8976 dynamic = rmb->refs != NULL;
8977 mp = dynamic ? NULL : klass->image->mempool;
8980 g_assert (!klass->generic_class);
8982 mono_loader_lock ();
8984 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8985 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8986 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8988 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8990 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8992 pm = (MonoMethodNormal*)m;
8994 m->dynamic = dynamic;
8996 m->flags = rmb->attrs;
8997 m->iflags = rmb->iattrs;
8998 m->name = mp_string_to_utf8 (mp, rmb->name);
9001 m->skip_visibility = rmb->skip_visibility;
9003 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9005 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9006 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9009 m->signature->pinvoke = 1;
9010 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9011 m->signature->pinvoke = 1;
9013 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9015 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
9016 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
9018 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9020 if (klass->image->dynamic)
9021 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9023 mono_loader_unlock ();
9026 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9027 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9028 MonoMethodHeader *header;
9030 gint32 max_stack, i;
9031 gint32 num_locals = 0;
9032 gint32 num_clauses = 0;
9036 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9037 code_size = rmb->ilgen->code_len;
9038 max_stack = rmb->ilgen->max_stack;
9039 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9040 if (rmb->ilgen->ex_handlers)
9041 num_clauses = method_count_clauses (rmb->ilgen);
9044 code = mono_array_addr (rmb->code, guint8, 0);
9045 code_size = mono_array_length (rmb->code);
9046 /* we probably need to run a verifier on the code... */
9056 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
9057 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9058 header->code_size = code_size;
9059 header->code = mp_g_malloc (mp, code_size);
9060 memcpy ((char*)header->code, code, code_size);
9061 header->max_stack = max_stack;
9062 header->init_locals = rmb->init_locals;
9063 header->num_locals = num_locals;
9065 for (i = 0; i < num_locals; ++i) {
9066 MonoReflectionLocalBuilder *lb =
9067 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9069 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
9070 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9073 header->num_clauses = num_clauses;
9075 header->clauses = method_encode_clauses (mp, (MonoDynamicImage*)klass->image,
9076 rmb->ilgen, num_clauses);
9079 pm->header = header;
9082 if (rmb->generic_params) {
9083 int count = mono_array_length (rmb->generic_params);
9084 MonoGenericContainer *container;
9086 container = rmb->generic_container;
9088 m->is_generic = TRUE;
9089 mono_method_set_generic_container (m, container);
9091 container->type_argc = count;
9092 container->type_params = mp_g_new0 (mp, MonoGenericParam, count);
9093 container->owner.method = m;
9095 for (i = 0; i < count; i++) {
9096 MonoReflectionGenericParam *gp =
9097 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9099 container->type_params [i] = *gp->type.type->data.generic_param;
9102 if (klass->generic_container) {
9103 container->parent = klass->generic_container;
9104 container->context.class_inst = klass->generic_container->context.class_inst;
9106 container->context.method_inst = mono_get_shared_generic_inst (container);
9110 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9114 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9116 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
9117 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9118 for (i = 0; i < rmb->nrefs; ++i)
9119 data [i + 1] = rmb->refs [i];
9124 /* Parameter info */
9127 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9128 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
9129 for (i = 0; i <= m->signature->param_count; ++i) {
9130 MonoReflectionParamBuilder *pb;
9131 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9132 if ((i > 0) && (pb->attrs)) {
9133 /* Make a copy since it might point to a shared type structure */
9134 m->signature->params [i - 1] = mono_metadata_type_dup (mp, m->signature->params [i - 1]);
9135 m->signature->params [i - 1]->attrs = pb->attrs;
9138 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9139 MonoDynamicImage *assembly;
9140 guint32 idx, def_type, len;
9144 if (!method_aux->param_defaults) {
9145 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
9146 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
9148 assembly = (MonoDynamicImage*)klass->image;
9149 idx = encode_constant (assembly, pb->def_value, &def_type);
9150 /* Copy the data from the blob since it might get realloc-ed */
9151 p = assembly->blob.data + idx;
9152 len = mono_metadata_decode_blob_size (p, &p2);
9154 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
9155 method_aux->param_default_types [i] = def_type;
9156 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9160 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
9162 if (!method_aux->param_cattr)
9163 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
9164 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (mp, klass->image, pb->cattrs);
9170 /* Parameter marshalling */
9173 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9174 MonoReflectionParamBuilder *pb;
9175 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9176 if (pb->marshal_info) {
9178 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
9179 specs [pb->position] =
9180 mono_marshal_spec_from_builder (mp, klass->image->assembly, pb->marshal_info);
9184 if (specs != NULL) {
9186 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9187 method_aux->param_marshall = specs;
9190 if (klass->image->dynamic && method_aux)
9191 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9193 mono_loader_unlock ();
9199 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9201 ReflectionMethodBuilder rmb;
9202 MonoMethodSignature *sig;
9204 mono_loader_lock ();
9205 sig = ctor_builder_to_signature (klass->image->mempool, mb);
9206 mono_loader_unlock ();
9208 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9210 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9211 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9213 /* If we are in a generic class, we might be called multiple times from inflate_method */
9214 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9215 /* ilgen is no longer needed */
9223 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9225 ReflectionMethodBuilder rmb;
9226 MonoMethodSignature *sig;
9228 mono_loader_lock ();
9229 sig = method_builder_to_signature (klass->image->mempool, mb);
9230 mono_loader_unlock ();
9232 reflection_methodbuilder_from_method_builder (&rmb, mb);
9234 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9235 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9237 /* If we are in a generic class, we might be called multiple times from inflate_method */
9238 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9239 /* ilgen is no longer needed */
9245 static MonoClassField*
9246 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9248 MonoClassField *field;
9252 field = g_new0 (MonoClassField, 1);
9254 field->name = mono_string_to_utf8 (fb->name);
9256 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9257 field->type->attrs = fb->attrs;
9259 field->type = fb->type->type;
9261 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9262 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
9263 if (fb->offset != -1)
9264 field->offset = fb->offset;
9265 field->parent = klass;
9266 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9268 if (fb->def_value) {
9269 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9270 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9271 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9272 /* Copy the data from the blob since it might get realloc-ed */
9273 p = assembly->blob.data + idx;
9274 len = mono_metadata_decode_blob_size (p, &p2);
9276 field->data = g_malloc (len);
9277 memcpy ((gpointer)field->data, p, len);
9284 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9287 MonoReflectionTypeBuilder *tb = NULL;
9288 gboolean is_dynamic = FALSE;
9292 mono_loader_lock ();
9294 domain = mono_object_domain (type);
9296 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9297 tb = (MonoReflectionTypeBuilder *) type;
9300 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9301 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9303 tb = rgi->generic_type;
9307 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9308 if (tb && tb->generic_container)
9309 mono_reflection_create_generic_class (tb);
9311 klass = mono_class_from_mono_type (type->type);
9312 if (!klass->generic_container) {
9313 mono_loader_unlock ();
9317 if (klass->wastypebuilder) {
9318 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9323 mono_loader_unlock ();
9325 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9327 return &geninst->byval_arg;
9331 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9333 MonoGenericClass *gclass;
9334 MonoGenericInst *inst;
9336 g_assert (klass->generic_container);
9338 inst = mono_metadata_get_generic_inst (type_argc, types);
9339 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9341 return mono_generic_class_get_class (gclass);
9344 MonoReflectionMethod*
9345 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9348 MonoMethod *method, *inflated;
9349 MonoMethodInflated *imethod;
9350 MonoReflectionMethodBuilder *mb = NULL;
9351 MonoGenericContext tmp_context;
9352 MonoGenericInst *ginst;
9353 MonoType **type_argv;
9356 MONO_ARCH_SAVE_REGS;
9357 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9358 MonoReflectionTypeBuilder *tb;
9361 mb = (MonoReflectionMethodBuilder *) rmethod;
9362 tb = (MonoReflectionTypeBuilder *) mb->type;
9363 klass = mono_class_from_mono_type (tb->type.type);
9365 method = methodbuilder_to_mono_method (klass, mb);
9367 method = rmethod->method;
9370 klass = method->klass;
9372 if (method->is_inflated)
9373 method = ((MonoMethodInflated *) method)->declaring;
9375 count = mono_method_signature (method)->generic_param_count;
9376 if (count != mono_array_length (types))
9379 type_argv = g_new0 (MonoType *, count);
9380 for (i = 0; i < count; i++) {
9381 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9382 type_argv [i] = garg->type;
9384 ginst = mono_metadata_get_generic_inst (count, type_argv);
9387 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9388 tmp_context.method_inst = ginst;
9390 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9391 imethod = (MonoMethodInflated *) inflated;
9393 if (method->klass->image->dynamic) {
9394 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9396 * This table maps metadata structures representing inflated methods/fields
9397 * to the reflection objects representing their generic definitions.
9399 mono_loader_lock ();
9400 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9401 mono_loader_unlock ();
9404 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9408 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9410 MonoMethodInflated *imethod;
9411 MonoGenericContext *context;
9414 g_assert (klass->generic_class);
9415 context = mono_class_get_context (klass);
9417 if (klass->method.count) {
9418 /* Find the already created inflated method */
9419 for (i = 0; i < klass->method.count; ++i) {
9420 g_assert (klass->methods [i]->is_inflated);
9421 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9424 g_assert (i < klass->method.count);
9425 imethod = (MonoMethodInflated*)klass->methods [i];
9427 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9430 if (method->is_generic && method->klass->image->dynamic) {
9431 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9433 mono_loader_lock ();
9434 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9435 mono_loader_unlock ();
9437 return (MonoMethod *) imethod;
9441 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9446 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9448 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9449 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9450 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9452 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9453 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9454 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9455 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9456 method = ((MonoReflectionMethod *) obj)->method;
9458 method = NULL; /* prevent compiler warning */
9459 g_assert_not_reached ();
9462 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9465 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9467 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9468 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9471 MonoGenericClass *gclass;
9472 MonoDynamicGenericClass *dgclass;
9473 MonoClass *klass, *gklass;
9476 MONO_ARCH_SAVE_REGS;
9478 klass = mono_class_from_mono_type (type->type.type);
9479 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9480 gclass = type->type.type->data.generic_class;
9482 g_assert (gclass->is_dynamic);
9483 dgclass = (MonoDynamicGenericClass *) gclass;
9485 if (dgclass->initialized)
9488 gklass = gclass->container_class;
9489 mono_class_init (gklass);
9491 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9492 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9493 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9494 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9495 dgclass->count_events = events ? mono_array_length (events) : 0;
9497 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9498 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9499 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9500 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9501 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9503 for (i = 0; i < dgclass->count_methods; i++) {
9504 MonoObject *obj = mono_array_get (methods, gpointer, i);
9506 dgclass->methods [i] = inflate_method (type, obj);
9509 for (i = 0; i < dgclass->count_ctors; i++) {
9510 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9512 dgclass->ctors [i] = inflate_method (type, obj);
9515 for (i = 0; i < dgclass->count_fields; i++) {
9516 MonoObject *obj = mono_array_get (fields, gpointer, i);
9517 MonoClassField *field, *inflated_field = NULL;
9518 MonoInflatedField *ifield;
9520 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9521 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9522 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9523 field = ((MonoReflectionField *) obj)->field;
9525 field = NULL; /* prevent compiler warning */
9526 g_assert_not_reached ();
9529 ifield = g_new0 (MonoInflatedField, 1);
9530 ifield->generic_type = field->type;
9531 MOVING_GC_REGISTER (&ifield->reflection_info);
9532 ifield->reflection_info = obj;
9534 dgclass->fields [i] = *field;
9535 dgclass->fields [i].parent = klass;
9536 dgclass->fields [i].generic_info = ifield;
9537 dgclass->fields [i].type = mono_class_inflate_generic_type (
9538 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9540 if (inflated_field) {
9541 g_free ((char*)inflated_field->data);
9542 g_free (inflated_field);
9544 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9548 for (i = 0; i < dgclass->count_properties; i++) {
9549 MonoObject *obj = mono_array_get (properties, gpointer, i);
9550 MonoProperty *property = &dgclass->properties [i];
9552 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9553 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9555 property->parent = klass;
9556 property->attrs = pb->attrs;
9557 property->name = mono_string_to_utf8 (pb->name);
9559 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9561 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9562 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9563 *property = *((MonoReflectionProperty *) obj)->property;
9564 property->name = g_strdup (property->name);
9567 property->get = inflate_mono_method (klass, property->get, NULL);
9569 property->set = inflate_mono_method (klass, property->set, NULL);
9571 g_assert_not_reached ();
9574 for (i = 0; i < dgclass->count_events; i++) {
9575 MonoObject *obj = mono_array_get (events, gpointer, i);
9576 MonoEvent *event = &dgclass->events [i];
9578 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9579 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9581 event->parent = klass;
9582 event->attrs = eb->attrs;
9583 event->name = mono_string_to_utf8 (eb->name);
9585 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9586 if (eb->remove_method)
9587 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9588 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9589 *event = *((MonoReflectionEvent *) obj)->event;
9590 event->name = g_strdup (event->name);
9593 event->add = inflate_mono_method (klass, event->add, NULL);
9595 event->remove = inflate_mono_method (klass, event->remove, NULL);
9597 g_assert_not_reached ();
9600 dgclass->initialized = TRUE;
9604 ensure_runtime_vtable (MonoClass *klass)
9606 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9609 if (!tb || klass->wastypebuilder)
9612 ensure_runtime_vtable (klass->parent);
9614 num = tb->ctors? mono_array_length (tb->ctors): 0;
9615 num += tb->num_methods;
9616 klass->method.count = num;
9617 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9618 num = tb->ctors? mono_array_length (tb->ctors): 0;
9619 for (i = 0; i < num; ++i)
9620 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9621 num = tb->num_methods;
9623 for (i = 0; i < num; ++i)
9624 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9626 if (tb->interfaces) {
9627 klass->interface_count = mono_array_length (tb->interfaces);
9628 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9629 for (i = 0; i < klass->interface_count; ++i) {
9630 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9631 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9635 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9636 for (i = 0; i < klass->method.count; ++i)
9637 klass->methods [i]->slot = i;
9639 mono_class_setup_interface_offsets (klass);
9643 * The generic vtable is needed even if image->run is not set since some
9644 * runtime code like ves_icall_Type_GetMethodsByName depends on
9645 * method->slot being defined.
9649 * tb->methods could not be freed since it is used for determining
9650 * overrides during dynamic vtable construction.
9655 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9657 MonoReflectionTypeBuilder *tb;
9663 g_assert (klass->image->dynamic);
9665 if (!klass->reflection_info)
9668 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9670 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9674 for (i = 0; i < tb->num_methods; ++i) {
9675 MonoReflectionMethodBuilder *mb =
9676 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9677 if (mb->override_method)
9683 *overrides = g_new0 (MonoMethod*, onum * 2);
9686 for (i = 0; i < tb->num_methods; ++i) {
9687 MonoReflectionMethodBuilder *mb =
9688 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9689 if (mb->override_method) {
9690 (*overrides) [onum * 2] =
9691 mb->override_method->method;
9692 (*overrides) [onum * 2 + 1] =
9695 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9696 g_assert (mb->override_method->method);
9697 g_assert (mb->mhandle);
9704 *num_overrides = onum;
9708 typebuilder_setup_fields (MonoClass *klass)
9710 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9711 MonoReflectionFieldBuilder *fb;
9712 MonoClassField *field;
9713 MonoMemPool *mp = klass->image->mempool;
9718 klass->field.count = tb->num_fields;
9719 klass->field.first = 0;
9721 if (!klass->field.count)
9724 klass->fields = mp_g_new0 (mp, MonoClassField, klass->field.count);
9726 for (i = 0; i < klass->field.count; ++i) {
9727 fb = mono_array_get (tb->fields, gpointer, i);
9728 field = &klass->fields [i];
9729 field->name = mp_string_to_utf8 (mp, fb->name);
9731 field->type = mono_metadata_type_dup (mp, fb->type->type);
9732 field->type->attrs = fb->attrs;
9734 field->type = fb->type->type;
9736 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9737 field->data = mono_array_addr (fb->rva_data, char, 0);
9738 if (fb->offset != -1)
9739 field->offset = fb->offset;
9740 field->parent = klass;
9742 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9744 if (fb->def_value) {
9745 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9746 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9747 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9748 /* Copy the data from the blob since it might get realloc-ed */
9749 p = assembly->blob.data + idx;
9750 len = mono_metadata_decode_blob_size (p, &p2);
9752 field->data = mono_mempool_alloc (mp, len);
9753 memcpy ((gpointer)field->data, p, len);
9756 mono_class_layout_fields (klass);
9760 typebuilder_setup_properties (MonoClass *klass)
9762 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9763 MonoReflectionPropertyBuilder *pb;
9764 MonoMemPool *mp = klass->image->mempool;
9767 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9768 klass->property.first = 0;
9770 klass->properties = mp_g_new0 (mp, MonoProperty, klass->property.count);
9771 for (i = 0; i < klass->property.count; ++i) {
9772 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9773 klass->properties [i].parent = klass;
9774 klass->properties [i].attrs = pb->attrs;
9775 klass->properties [i].name = mp_string_to_utf8 (mp, pb->name);
9777 klass->properties [i].get = pb->get_method->mhandle;
9779 klass->properties [i].set = pb->set_method->mhandle;
9781 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9785 MonoReflectionEvent *
9786 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9788 MonoEvent *event = g_new0 (MonoEvent, 1);
9792 klass = my_mono_class_from_mono_type (tb->type.type);
9794 event->parent = klass;
9795 event->attrs = eb->attrs;
9796 event->name = mono_string_to_utf8 (eb->name);
9798 event->add = eb->add_method->mhandle;
9799 if (eb->remove_method)
9800 event->remove = eb->remove_method->mhandle;
9801 if (eb->raise_method)
9802 event->raise = eb->raise_method->mhandle;
9804 if (eb->other_methods) {
9805 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9806 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9807 MonoReflectionMethodBuilder *mb =
9808 mono_array_get (eb->other_methods,
9809 MonoReflectionMethodBuilder*, j);
9810 event->other [j] = mb->mhandle;
9814 return mono_event_get_object (mono_object_domain (tb), klass, event);
9818 typebuilder_setup_events (MonoClass *klass)
9820 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9821 MonoReflectionEventBuilder *eb;
9822 MonoMemPool *mp = klass->image->mempool;
9825 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9826 klass->event.first = 0;
9828 klass->events = mp_g_new0 (mp, MonoEvent, klass->event.count);
9829 for (i = 0; i < klass->event.count; ++i) {
9830 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9831 klass->events [i].parent = klass;
9832 klass->events [i].attrs = eb->attrs;
9833 klass->events [i].name = mp_string_to_utf8 (mp, eb->name);
9835 klass->events [i].add = eb->add_method->mhandle;
9836 if (eb->remove_method)
9837 klass->events [i].remove = eb->remove_method->mhandle;
9838 if (eb->raise_method)
9839 klass->events [i].raise = eb->raise_method->mhandle;
9841 if (eb->other_methods) {
9842 klass->events [i].other = mp_g_new0 (mp, MonoMethod*, mono_array_length (eb->other_methods) + 1);
9843 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9844 MonoReflectionMethodBuilder *mb =
9845 mono_array_get (eb->other_methods,
9846 MonoReflectionMethodBuilder*, j);
9847 klass->events [i].other [j] = mb->mhandle;
9850 mono_save_custom_attrs (klass->image, &klass->events [i], eb->cattrs);
9855 remove_instantiations_of (gpointer key,
9859 MonoType *type = (MonoType*)key;
9860 MonoClass *klass = (MonoClass*)user_data;
9862 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
9869 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9873 MonoReflectionType* res;
9876 MONO_ARCH_SAVE_REGS;
9878 domain = mono_object_domain (tb);
9879 klass = my_mono_class_from_mono_type (tb->type.type);
9881 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9884 * we need to lock the domain because the lock will be taken inside
9885 * So, we need to keep the locking order correct.
9887 mono_domain_lock (domain);
9888 mono_loader_lock ();
9889 if (klass->wastypebuilder) {
9890 mono_loader_unlock ();
9891 mono_domain_unlock (domain);
9892 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9895 * Fields to set in klass:
9896 * the various flags: delegate/unicode/contextbound etc.
9898 klass->flags = tb->attrs;
9899 klass->has_cctor = 1;
9900 klass->has_finalize = 1;
9903 if (!((MonoDynamicImage*)klass->image)->run) {
9904 if (klass->generic_container) {
9905 /* FIXME: The code below can't handle generic classes */
9906 klass->wastypebuilder = TRUE;
9907 mono_loader_unlock ();
9908 mono_domain_unlock (domain);
9909 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9914 /* enums are done right away */
9915 if (!klass->enumtype)
9916 ensure_runtime_vtable (klass);
9919 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9920 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9921 klass->nested_classes = g_list_prepend_mempool (klass->image->mempool, klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9925 klass->nested_classes_inited = TRUE;
9927 /* fields and object layout */
9928 if (klass->parent) {
9929 if (!klass->parent->size_inited)
9930 mono_class_init (klass->parent);
9931 klass->instance_size = klass->parent->instance_size;
9932 klass->sizes.class_size = 0;
9933 klass->min_align = klass->parent->min_align;
9934 /* if the type has no fields we won't call the field_setup
9935 * routine which sets up klass->has_references.
9937 klass->has_references |= klass->parent->has_references;
9939 klass->instance_size = sizeof (MonoObject);
9940 klass->min_align = 1;
9943 /* FIXME: handle packing_size and instance_size */
9944 typebuilder_setup_fields (klass);
9946 typebuilder_setup_properties (klass);
9948 typebuilder_setup_events (klass);
9950 klass->wastypebuilder = TRUE;
9953 * If we are a generic TypeBuilder, there might be instantiations in the type cache
9954 * which have type System.Reflection.MonoGenericClass, but after the type is created,
9955 * we want to return normal System.MonoType objects, so clear these out from the cache.
9957 if (domain->type_hash && klass->generic_container)
9958 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
9960 mono_loader_unlock ();
9961 mono_domain_unlock (domain);
9963 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
9964 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
9965 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
9968 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9969 g_assert (res != (MonoReflectionType*)tb);
9975 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9977 MonoGenericParam *param;
9980 MONO_ARCH_SAVE_REGS;
9982 param = g_new0 (MonoGenericParam, 1);
9984 if (gparam->mbuilder) {
9985 if (!gparam->mbuilder->generic_container) {
9986 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
9987 MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
9988 gparam->mbuilder->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
9989 gparam->mbuilder->generic_container->is_method = TRUE;
9991 param->owner = gparam->mbuilder->generic_container;
9992 } else if (gparam->tbuilder) {
9993 g_assert (gparam->tbuilder->generic_container);
9994 param->owner = gparam->tbuilder->generic_container;
9997 param->name = mono_string_to_utf8 (gparam->name);
9998 param->num = gparam->index;
10000 image = &gparam->tbuilder->module->dynamic_image->image;
10001 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10003 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
10004 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10006 gparam->type.type = g_new0 (MonoType, 1);
10007 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
10008 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
10009 gparam->type.type->data.generic_param = param;
10013 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10015 MonoDynamicImage *assembly = sig->module->dynamic_image;
10016 guint32 na = mono_array_length (sig->arguments);
10021 sigbuffer_init (&buf, 32);
10023 sigbuffer_add_value (&buf, 0x07);
10024 sigbuffer_add_value (&buf, na);
10025 for (i = 0; i < na; ++i) {
10026 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10027 encode_reflection_type (assembly, type, &buf);
10030 buflen = buf.p - buf.buf;
10031 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10032 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10033 sigbuffer_free (&buf);
10039 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10041 MonoDynamicImage *assembly = sig->module->dynamic_image;
10042 guint32 na = mono_array_length (sig->arguments);
10047 sigbuffer_init (&buf, 32);
10049 sigbuffer_add_value (&buf, 0x06);
10050 for (i = 0; i < na; ++i) {
10051 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10052 encode_reflection_type (assembly, type, &buf);
10055 buflen = buf.p - buf.buf;
10056 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10057 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10058 sigbuffer_free (&buf);
10064 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10066 ReflectionMethodBuilder rmb;
10067 MonoMethodSignature *sig;
10072 sig = dynamic_method_to_signature (mb);
10074 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10077 * Resolve references.
10080 * Every second entry in the refs array is reserved for storing handle_class,
10081 * which is needed by the ldtoken implementation in the JIT.
10083 rmb.nrefs = mb->nrefs;
10084 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10085 for (i = 0; i < mb->nrefs; i += 2) {
10086 MonoClass *handle_class;
10088 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10090 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10091 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10093 * The referenced DynamicMethod should already be created by the managed
10094 * code, except in the case of circular references. In that case, we store
10095 * method in the refs array, and fix it up later when the referenced
10096 * DynamicMethod is created.
10098 if (method->mhandle) {
10099 ref = method->mhandle;
10101 /* FIXME: GC object stored in unmanaged memory */
10104 /* FIXME: GC object stored in unmanaged memory */
10105 method->referenced_by = g_slist_append (method->referenced_by, mb);
10107 handle_class = mono_defaults.methodhandle_class;
10109 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10112 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10117 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10118 rmb.refs [i + 1] = handle_class;
10121 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10123 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10125 /* Fix up refs entries pointing at us */
10126 for (l = mb->referenced_by; l; l = l->next) {
10127 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10128 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10131 g_assert (method->mhandle);
10133 data = (gpointer*)wrapper->method_data;
10134 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10135 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10136 data [i + 1] = mb->mhandle;
10139 g_slist_free (mb->referenced_by);
10143 /* ilgen is no longer needed */
10148 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10153 mono_runtime_free_method (
10154 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10159 * mono_reflection_is_valid_dynamic_token:
10161 * Returns TRUE if token is valid.
10165 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10167 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10171 * mono_reflection_lookup_dynamic_token:
10173 * Finish the Builder object pointed to by TOKEN and return the corresponding
10174 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10175 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10179 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10181 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10185 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10188 g_assert_not_reached ();
10194 handle_class = &klass;
10195 return resolve_object (image, obj, handle_class, context);
10199 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10201 gpointer result = NULL;
10203 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10204 result = mono_string_intern ((MonoString*)obj);
10205 *handle_class = NULL;
10207 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10208 MonoReflectionType *tb = (MonoReflectionType*)obj;
10210 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10211 result = mono_class_from_mono_type (inflated);
10212 mono_metadata_free_type (inflated);
10214 result = mono_class_from_mono_type (tb->type);
10216 *handle_class = mono_defaults.typehandle_class;
10218 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10219 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10220 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10221 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10222 result = ((MonoReflectionMethod*)obj)->method;
10224 result = mono_class_inflate_generic_method (result, context);
10225 *handle_class = mono_defaults.methodhandle_class;
10227 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10228 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10229 result = mb->mhandle;
10231 /* Type is not yet created */
10232 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10234 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10237 * Hopefully this has been filled in by calling CreateType() on the
10241 * TODO: This won't work if the application finishes another
10242 * TypeBuilder instance instead of this one.
10244 result = mb->mhandle;
10247 result = mono_class_inflate_generic_method (result, context);
10248 *handle_class = mono_defaults.methodhandle_class;
10249 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10250 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10252 result = cb->mhandle;
10254 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10256 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10257 result = cb->mhandle;
10260 result = mono_class_inflate_generic_method (result, context);
10261 *handle_class = mono_defaults.methodhandle_class;
10262 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10263 result = ((MonoReflectionField*)obj)->field;
10264 *handle_class = mono_defaults.fieldhandle_class;
10266 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10267 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10268 result = fb->handle;
10271 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10273 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10274 result = fb->handle;
10277 if (fb->handle && fb->handle->parent->generic_container) {
10278 MonoClass *klass = fb->handle->parent;
10279 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10280 MonoClass *inflated = mono_class_from_mono_type (type);
10282 result = mono_class_get_field_from_name (inflated, fb->handle->name);
10284 mono_metadata_free_type (type);
10286 *handle_class = mono_defaults.fieldhandle_class;
10287 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10288 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10291 klass = tb->type.type->data.klass;
10292 if (klass->wastypebuilder) {
10293 /* Already created */
10297 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10298 result = tb->type.type->data.klass;
10301 *handle_class = mono_defaults.typehandle_class;
10302 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10303 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10304 MonoMethodSignature *sig;
10307 if (helper->arguments)
10308 nargs = mono_array_length (helper->arguments);
10312 sig = mono_metadata_signature_alloc (image, nargs);
10313 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10314 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10316 if (helper->call_conv == 0) /* unmanaged */
10317 sig->call_convention = helper->unmanaged_call_conv - 1;
10319 if (helper->call_conv & 0x02)
10320 sig->call_convention = MONO_CALL_VARARG;
10322 sig->call_convention = MONO_CALL_DEFAULT;
10324 sig->param_count = nargs;
10325 /* TODO: Copy type ? */
10326 sig->ret = helper->return_type->type;
10327 for (i = 0; i < nargs; ++i) {
10328 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10329 sig->params [i] = rt->type;
10333 *handle_class = NULL;
10334 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10335 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10336 /* Already created by the managed code */
10337 g_assert (method->mhandle);
10338 result = method->mhandle;
10339 *handle_class = mono_defaults.methodhandle_class;
10340 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10341 MonoReflectionType *tb = (MonoReflectionType*)obj;
10342 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10343 result = mono_class_from_mono_type (type);
10344 *handle_class = mono_defaults.typehandle_class;
10346 mono_metadata_free_type (type);
10347 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10348 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10349 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10350 result = mono_class_from_mono_type (type);
10351 *handle_class = mono_defaults.typehandle_class;
10353 mono_metadata_free_type (type);
10354 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10355 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10356 MonoClass *inflated;
10359 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10360 inflated = mono_class_from_mono_type (type);
10362 g_assert (f->fb->handle);
10363 result = mono_class_get_field_from_name (inflated, f->fb->handle->name);
10365 mono_metadata_free_type (type);
10366 *handle_class = mono_defaults.fieldhandle_class;
10367 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10368 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10369 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10370 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10371 g_assert (c->cb->mhandle);
10372 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10373 *handle_class = mono_defaults.methodhandle_class;
10374 mono_metadata_free_type (type);
10375 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10376 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10377 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10378 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10379 g_assert (m->mb->mhandle);
10380 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10381 *handle_class = mono_defaults.methodhandle_class;
10382 mono_metadata_free_type (type);
10384 g_print (obj->vtable->klass->name);
10385 g_assert_not_reached ();
10391 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10392 const static guint32 declsec_flags_map[] = {
10393 0x00000000, /* empty */
10394 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10395 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10396 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10397 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10398 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10399 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10400 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10401 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10402 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10403 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10404 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10405 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10406 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10407 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10408 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10409 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10410 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10411 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10415 * Returns flags that includes all available security action associated to the handle.
10416 * @token: metadata token (either for a class or a method)
10417 * @image: image where resides the metadata.
10420 mono_declsec_get_flags (MonoImage *image, guint32 token)
10422 int index = mono_metadata_declsec_from_index (image, token);
10423 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10424 guint32 result = 0;
10428 /* HasSecurity can be present for other, not specially encoded, attributes,
10429 e.g. SuppressUnmanagedCodeSecurityAttribute */
10433 for (i = index; i < t->rows; i++) {
10434 guint32 cols [MONO_DECL_SECURITY_SIZE];
10436 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10437 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10440 action = cols [MONO_DECL_SECURITY_ACTION];
10441 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10442 result |= declsec_flags_map [action];
10444 g_assert_not_reached ();
10451 * Get the security actions (in the form of flags) associated with the specified method.
10453 * @method: The method for which we want the declarative security flags.
10454 * Return the declarative security flags for the method (only).
10456 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10457 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10460 mono_declsec_flags_from_method (MonoMethod *method)
10462 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10463 /* FIXME: No cache (for the moment) */
10464 guint32 idx = mono_method_get_index (method);
10465 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10466 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10467 return mono_declsec_get_flags (method->klass->image, idx);
10473 * Get the security actions (in the form of flags) associated with the specified class.
10475 * @klass: The class for which we want the declarative security flags.
10476 * Return the declarative security flags for the class.
10478 * Note: We cache the flags inside the MonoClass structure as this will get
10479 * called very often (at least for each method).
10482 mono_declsec_flags_from_class (MonoClass *klass)
10484 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10485 if (!klass->declsec_flags) {
10486 guint32 idx = mono_metadata_token_index (klass->type_token);
10487 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10488 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10489 /* we cache the flags on classes */
10490 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10492 return klass->declsec_flags;
10498 * Get the security actions (in the form of flags) associated with the specified assembly.
10500 * @assembly: The assembly for which we want the declarative security flags.
10501 * Return the declarative security flags for the assembly.
10504 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10506 guint32 idx = 1; /* there is only one assembly */
10507 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10508 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10509 return mono_declsec_get_flags (assembly->image, idx);
10514 * Fill actions for the specific index (which may either be an encoded class token or
10515 * an encoded method token) from the metadata image.
10516 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10519 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10520 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10522 MonoBoolean result = FALSE;
10524 guint32 cols [MONO_DECL_SECURITY_SIZE];
10525 int index = mono_metadata_declsec_from_index (image, token);
10528 t = &image->tables [MONO_TABLE_DECLSECURITY];
10529 for (i = index; i < t->rows; i++) {
10530 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10532 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10535 /* if present only replace (class) permissions with method permissions */
10536 /* if empty accept either class or method permissions */
10537 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10538 if (!actions->demand.blob) {
10539 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10540 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10541 actions->demand.blob = (char*) (blob + 2);
10542 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10545 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10546 if (!actions->noncasdemand.blob) {
10547 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10548 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10549 actions->noncasdemand.blob = (char*) (blob + 2);
10550 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10553 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10554 if (!actions->demandchoice.blob) {
10555 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10556 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10557 actions->demandchoice.blob = (char*) (blob + 2);
10558 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10568 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
10569 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10571 guint32 idx = mono_metadata_token_index (klass->type_token);
10572 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10573 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10574 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
10578 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
10579 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10581 guint32 idx = mono_method_get_index (method);
10582 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10583 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10584 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10588 * Collect all actions (that requires to generate code in mini) assigned for
10589 * the specified method.
10590 * Note: Don't use the content of actions if the function return FALSE.
10593 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10595 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
10596 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10597 MonoBoolean result = FALSE;
10600 /* quick exit if no declarative security is present in the metadata */
10601 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10604 /* we want the original as the wrapper is "free" of the security informations */
10605 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10606 method = mono_marshal_method_from_wrapper (method);
10611 /* First we look for method-level attributes */
10612 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10613 mono_class_init (method->klass);
10614 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10616 result = mono_declsec_get_method_demands_params (method, demands,
10617 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10620 /* Here we use (or create) the class declarative cache to look for demands */
10621 flags = mono_declsec_flags_from_class (method->klass);
10622 if (flags & mask) {
10624 mono_class_init (method->klass);
10625 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10627 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10628 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10631 /* The boolean return value is used as a shortcut in case nothing needs to
10632 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10638 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10640 * Note: Don't use the content of actions if the function return FALSE.
10643 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10645 MonoBoolean result = FALSE;
10648 /* quick exit if no declarative security is present in the metadata */
10649 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10652 /* we want the original as the wrapper is "free" of the security informations */
10653 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10654 method = mono_marshal_method_from_wrapper (method);
10659 /* results are independant - zeroize both */
10660 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10661 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10663 /* First we look for method-level attributes */
10664 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10665 mono_class_init (method->klass);
10667 result = mono_declsec_get_method_demands_params (method, cmethod,
10668 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10671 /* Here we use (or create) the class declarative cache to look for demands */
10672 flags = mono_declsec_flags_from_class (method->klass);
10673 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10674 mono_class_init (method->klass);
10676 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10677 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10684 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10686 * @klass The inherited class - this is the class that provides the security check (attributes)
10688 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10690 * Note: Don't use the content of actions if the function return FALSE.
10693 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10695 MonoBoolean result = FALSE;
10698 /* quick exit if no declarative security is present in the metadata */
10699 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10702 /* Here we use (or create) the class declarative cache to look for demands */
10703 flags = mono_declsec_flags_from_class (klass);
10704 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10705 mono_class_init (klass);
10706 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10708 result |= mono_declsec_get_class_demands_params (klass, demands,
10709 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10716 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10718 * Note: Don't use the content of actions if the function return FALSE.
10721 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10723 /* quick exit if no declarative security is present in the metadata */
10724 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10727 /* we want the original as the wrapper is "free" of the security informations */
10728 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10729 method = mono_marshal_method_from_wrapper (method);
10734 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10735 mono_class_init (method->klass);
10736 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10738 return mono_declsec_get_method_demands_params (method, demands,
10739 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10746 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10748 guint32 cols [MONO_DECL_SECURITY_SIZE];
10752 int index = mono_metadata_declsec_from_index (image, token);
10756 t = &image->tables [MONO_TABLE_DECLSECURITY];
10757 for (i = index; i < t->rows; i++) {
10758 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10760 /* shortcut - index are ordered */
10761 if (token != cols [MONO_DECL_SECURITY_PARENT])
10764 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10765 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10766 entry->blob = (char*) (metadata + 2);
10767 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10776 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10778 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10779 guint32 idx = mono_method_get_index (method);
10780 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10781 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10782 return get_declsec_action (method->klass->image, idx, action, entry);
10788 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10791 guint32 flags = mono_declsec_flags_from_class (klass);
10792 if (declsec_flags_map [action] & flags) {
10793 guint32 idx = mono_metadata_token_index (klass->type_token);
10794 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10795 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10796 return get_declsec_action (klass->image, idx, action, entry);
10802 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10804 guint32 idx = 1; /* there is only one assembly */
10805 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10806 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10808 return get_declsec_action (assembly->image, idx, action, entry);
10812 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10814 MonoObject *res, *exc;
10816 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10817 static MonoMethod *method = NULL;
10819 if (!System_Reflection_Emit_TypeBuilder) {
10820 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10821 g_assert (System_Reflection_Emit_TypeBuilder);
10823 if (method == NULL) {
10824 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10829 * The result of mono_type_get_object () might be a System.MonoType but we
10830 * need a TypeBuilder so use klass->reflection_info.
10832 g_assert (klass->reflection_info);
10833 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10835 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10837 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10841 return *(MonoBoolean*)mono_object_unbox (res);