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/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include <mono/metadata/profiler-private.h>
16 #include "mono/metadata/class-internals.h"
17 #include "mono/metadata/gc-internal.h"
18 #include "mono/metadata/tokentype.h"
19 #include "mono/metadata/domain-internals.h"
20 #include "mono/metadata/opcodes.h"
21 #include "mono/metadata/assembly.h"
22 #include "mono/metadata/object-internals.h"
23 #include <mono/metadata/exception.h>
24 #include <mono/metadata/marshal.h>
25 #include <mono/metadata/security-manager.h>
34 #include "rawbuffer.h"
35 #include "mono-endian.h"
36 #include <mono/metadata/gc-internal.h>
44 #define TEXT_OFFSET 512
45 #define CLI_H_SIZE 136
46 #define FILE_ALIGN 512
47 #define VIRT_ALIGN 8192
48 #define START_TEXT_RVA 0x00002000
51 MonoReflectionILGen *ilgen;
52 MonoReflectionType *rtype;
53 MonoArray *parameters;
54 MonoArray *generic_params;
55 MonoGenericContainer *generic_container;
61 guint32 *table_idx; /* note: it's a pointer */
65 MonoBoolean init_locals;
66 MonoBoolean skip_visibility;
67 MonoArray *return_modreq;
68 MonoArray *return_modopt;
69 MonoArray *param_modreq;
70 MonoArray *param_modopt;
71 MonoArray *permissions;
76 int charset, extra_flags, native_cc;
77 MonoString *dll, *dllentry;
78 } ReflectionMethodBuilder;
82 MonoReflectionGenericParam *gparam;
83 } GenericParamTableEntry;
85 const unsigned char table_sizes [MONO_TABLE_NUM] = {
95 MONO_INTERFACEIMPL_SIZE,
96 MONO_MEMBERREF_SIZE, /* 0x0A */
98 MONO_CUSTOM_ATTR_SIZE,
99 MONO_FIELD_MARSHAL_SIZE,
100 MONO_DECL_SECURITY_SIZE,
101 MONO_CLASS_LAYOUT_SIZE,
102 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
103 MONO_STAND_ALONE_SIGNATURE_SIZE,
107 MONO_PROPERTY_MAP_SIZE,
110 MONO_METHOD_SEMA_SIZE,
111 MONO_METHODIMPL_SIZE,
112 MONO_MODULEREF_SIZE, /* 0x1A */
118 MONO_ASSEMBLY_SIZE, /* 0x20 */
119 MONO_ASSEMBLY_PROCESSOR_SIZE,
120 MONO_ASSEMBLYOS_SIZE,
121 MONO_ASSEMBLYREF_SIZE,
122 MONO_ASSEMBLYREFPROC_SIZE,
123 MONO_ASSEMBLYREFOS_SIZE,
127 MONO_NESTED_CLASS_SIZE,
129 MONO_GENERICPARAM_SIZE, /* 0x2A */
130 MONO_METHODSPEC_SIZE,
131 MONO_GENPARCONSTRAINT_SIZE
135 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
136 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
137 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
138 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
139 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
140 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
141 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
142 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
143 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
144 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
145 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
146 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
147 static void ensure_runtime_vtable (MonoClass *klass);
148 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
149 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
150 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
151 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
152 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
153 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
155 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
156 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
157 static CRITICAL_SECTION reflection_mutex;
160 mono_reflection_init (void)
162 InitializeCriticalSection (&reflection_mutex);
166 sigbuffer_init (SigBuffer *buf, int size)
168 buf->buf = g_malloc (size);
170 buf->end = buf->buf + size;
174 sigbuffer_make_room (SigBuffer *buf, int size)
176 if (buf->end - buf->p < size) {
177 int new_size = buf->end - buf->buf + size + 32;
178 char *p = g_realloc (buf->buf, new_size);
179 size = buf->p - buf->buf;
182 buf->end = buf->buf + new_size;
187 sigbuffer_add_value (SigBuffer *buf, guint32 val)
189 sigbuffer_make_room (buf, 6);
190 mono_metadata_encode_value (val, buf->p, &buf->p);
194 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
196 sigbuffer_make_room (buf, 1);
202 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
204 sigbuffer_make_room (buf, size);
205 memcpy (buf->p, p, size);
210 sigbuffer_free (SigBuffer *buf)
218 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
222 mp_g_malloc (MonoMemPool *mp, guint size)
225 return mono_mempool_alloc (mp, size);
227 return g_malloc (size);
233 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
237 mp_g_malloc0 (MonoMemPool *mp, guint size)
240 return mono_mempool_alloc0 (mp, size);
242 return g_malloc0 (size);
248 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
249 * memory from the C heap.
252 mp_string_to_utf8 (MonoMemPool *mp, MonoString *s)
255 return mono_string_to_utf8_mp (mp, s);
257 return mono_string_to_utf8 (s);
260 #define mp_g_new(mp,struct_type, n_structs) \
261 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
263 #define mp_g_new0(mp,struct_type, n_structs) \
264 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
267 alloc_table (MonoDynamicTable *table, guint nrows)
270 g_assert (table->columns);
271 if (nrows + 1 >= table->alloc_rows) {
272 while (nrows + 1 >= table->alloc_rows) {
273 if (table->alloc_rows == 0)
274 table->alloc_rows = 16;
276 table->alloc_rows *= 2;
279 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
284 make_room_in_stream (MonoDynamicStream *stream, int size)
286 if (size <= stream->alloc_size)
289 while (stream->alloc_size <= size) {
290 if (stream->alloc_size < 4096)
291 stream->alloc_size = 4096;
293 stream->alloc_size *= 2;
296 stream->data = g_realloc (stream->data, stream->alloc_size);
300 string_heap_insert (MonoDynamicStream *sh, const char *str)
304 gpointer oldkey, oldval;
306 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
307 return GPOINTER_TO_UINT (oldval);
309 len = strlen (str) + 1;
312 make_room_in_stream (sh, idx + len);
315 * We strdup the string even if we already copy them in sh->data
316 * so that the string pointers in the hash remain valid even if
317 * we need to realloc sh->data. We may want to avoid that later.
319 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
320 memcpy (sh->data + idx, str, len);
326 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
328 char *name = mono_string_to_utf8 (str);
330 idx = string_heap_insert (sh, name);
336 string_heap_init (MonoDynamicStream *sh)
339 sh->alloc_size = 4096;
340 sh->data = g_malloc (4096);
341 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
342 string_heap_insert (sh, "");
346 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
350 make_room_in_stream (stream, stream->index + len);
351 memcpy (stream->data + stream->index, data, len);
353 stream->index += len;
355 * align index? Not without adding an additional param that controls it since
356 * we may store a blob value in pieces.
362 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
366 make_room_in_stream (stream, stream->index + len);
367 memset (stream->data + stream->index, 0, len);
369 stream->index += len;
374 stream_data_align (MonoDynamicStream *stream)
377 guint32 count = stream->index % 4;
379 /* we assume the stream data will be aligned */
381 mono_image_add_stream_data (stream, buf, 4 - count);
385 mono_blob_entry_hash (const char* str)
389 len = mono_metadata_decode_blob_size (str, &str);
393 for (str += 1; str < end; str++)
394 h = (h << 5) - h + *str;
402 mono_blob_entry_equal (const char *str1, const char *str2) {
406 len = mono_metadata_decode_blob_size (str1, &end1);
407 len2 = mono_metadata_decode_blob_size (str2, &end2);
410 return memcmp (end1, end2, len) == 0;
414 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
418 gpointer oldkey, oldval;
420 copy = g_malloc (s1+s2);
421 memcpy (copy, b1, s1);
422 memcpy (copy + s1, b2, s2);
423 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
425 idx = GPOINTER_TO_UINT (oldval);
427 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
428 mono_image_add_stream_data (&assembly->blob, b2, s2);
429 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
435 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
439 guint32 size = buf->p - buf->buf;
441 g_assert (size <= (buf->end - buf->buf));
442 mono_metadata_encode_value (size, b, &b);
443 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
447 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
448 * dest may be misaligned.
451 swap_with_size (char *dest, const char* val, int len, int nelem) {
452 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
455 for (elem = 0; elem < nelem; ++elem) {
481 g_assert_not_reached ();
487 memcpy (dest, val, len * nelem);
492 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
496 guint32 idx = 0, len;
498 len = str->length * 2;
499 mono_metadata_encode_value (len, b, &b);
500 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
502 char *swapped = g_malloc (2 * mono_string_length (str));
503 const char *p = (const char*)mono_string_chars (str);
505 swap_with_size (swapped, p, 2, mono_string_length (str));
506 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
510 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
515 /* modified version needed to handle building corlib */
517 my_mono_class_from_mono_type (MonoType *type) {
518 switch (type->type) {
519 case MONO_TYPE_ARRAY:
521 case MONO_TYPE_SZARRAY:
522 case MONO_TYPE_GENERICINST:
523 return mono_class_from_mono_type (type);
526 g_assert (type->data.generic_param->pklass);
527 return type->data.generic_param->pklass;
529 /* should be always valid when we reach this case... */
530 return type->data.klass;
535 default_class_from_mono_type (MonoType *type)
537 switch (type->type) {
538 case MONO_TYPE_OBJECT:
539 return mono_defaults.object_class;
541 return mono_defaults.void_class;
542 case MONO_TYPE_BOOLEAN:
543 return mono_defaults.boolean_class;
545 return mono_defaults.char_class;
547 return mono_defaults.sbyte_class;
549 return mono_defaults.byte_class;
551 return mono_defaults.int16_class;
553 return mono_defaults.uint16_class;
555 return mono_defaults.int32_class;
557 return mono_defaults.uint32_class;
559 return mono_defaults.int_class;
561 return mono_defaults.uint_class;
563 return mono_defaults.int64_class;
565 return mono_defaults.uint64_class;
567 return mono_defaults.single_class;
569 return mono_defaults.double_class;
570 case MONO_TYPE_STRING:
571 return mono_defaults.string_class;
573 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
574 g_assert_not_reached ();
581 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
584 MonoGenericInst *class_inst;
589 class_inst = gclass->context.class_inst;
591 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
592 klass = gclass->container_class;
593 sigbuffer_add_value (buf, klass->byval_arg.type);
594 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
596 sigbuffer_add_value (buf, class_inst->type_argc);
597 for (i = 0; i < class_inst->type_argc; ++i)
598 encode_type (assembly, class_inst->type_argv [i], buf);
603 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
606 g_assert_not_reached ();
611 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
615 case MONO_TYPE_BOOLEAN:
629 case MONO_TYPE_STRING:
630 case MONO_TYPE_OBJECT:
631 case MONO_TYPE_TYPEDBYREF:
632 sigbuffer_add_value (buf, type->type);
635 sigbuffer_add_value (buf, type->type);
636 encode_type (assembly, type->data.type, buf);
638 case MONO_TYPE_SZARRAY:
639 sigbuffer_add_value (buf, type->type);
640 encode_type (assembly, &type->data.klass->byval_arg, buf);
642 case MONO_TYPE_VALUETYPE:
643 case MONO_TYPE_CLASS: {
644 MonoClass *k = mono_class_from_mono_type (type);
646 if (k->generic_container) {
647 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
648 encode_generic_class (assembly, gclass, buf);
651 * Make sure we use the correct type.
653 sigbuffer_add_value (buf, k->byval_arg.type);
655 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
656 * otherwise two typerefs could point to the same type, leading to
657 * verification errors.
659 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
663 case MONO_TYPE_ARRAY:
664 sigbuffer_add_value (buf, type->type);
665 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
666 sigbuffer_add_value (buf, type->data.array->rank);
667 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
668 sigbuffer_add_value (buf, 0);
670 case MONO_TYPE_GENERICINST:
671 encode_generic_class (assembly, type->data.generic_class, buf);
675 sigbuffer_add_value (buf, type->type);
676 sigbuffer_add_value (buf, type->data.generic_param->num);
679 g_error ("need to encode type %x", type->type);
684 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
687 sigbuffer_add_value (buf, MONO_TYPE_VOID);
692 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
693 encode_type (assembly, type->type, buf);
697 g_assert_not_reached ();
702 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
707 for (i = 0; i < mono_array_length (modreq); ++i) {
708 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
709 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
710 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
714 for (i = 0; i < mono_array_length (modopt); ++i) {
715 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
716 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
717 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
723 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
727 guint32 nparams = sig->param_count;
733 sigbuffer_init (&buf, 32);
735 * FIXME: vararg, explicit_this, differenc call_conv values...
737 idx = sig->call_convention;
739 idx |= 0x20; /* hasthis */
740 if (sig->generic_param_count)
741 idx |= 0x10; /* generic */
742 sigbuffer_add_byte (&buf, idx);
743 if (sig->generic_param_count)
744 sigbuffer_add_value (&buf, sig->generic_param_count);
745 sigbuffer_add_value (&buf, nparams);
746 encode_type (assembly, sig->ret, &buf);
747 for (i = 0; i < nparams; ++i) {
748 if (i == sig->sentinelpos)
749 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
750 encode_type (assembly, sig->params [i], &buf);
752 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
753 sigbuffer_free (&buf);
758 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
761 * FIXME: reuse code from method_encode_signature().
765 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
766 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
767 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
770 sigbuffer_init (&buf, 32);
771 /* LAMESPEC: all the call conv spec is foobared */
772 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
773 if (mb->call_conv & 2)
774 idx |= 0x5; /* vararg */
775 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
776 idx |= 0x20; /* hasthis */
778 idx |= 0x10; /* generic */
779 sigbuffer_add_byte (&buf, idx);
781 sigbuffer_add_value (&buf, ngparams);
782 sigbuffer_add_value (&buf, nparams + notypes);
783 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
784 encode_reflection_type (assembly, mb->rtype, &buf);
785 for (i = 0; i < nparams; ++i) {
786 MonoArray *modreq = NULL;
787 MonoArray *modopt = NULL;
788 MonoReflectionType *pt;
790 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
791 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
792 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
793 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
794 encode_custom_modifiers (assembly, modreq, modopt, &buf);
795 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
796 encode_reflection_type (assembly, pt, &buf);
799 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
800 for (i = 0; i < notypes; ++i) {
801 MonoReflectionType *pt;
803 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
804 encode_reflection_type (assembly, pt, &buf);
807 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
808 sigbuffer_free (&buf);
813 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
815 MonoDynamicTable *table;
817 guint32 idx, sig_idx;
818 guint nl = mono_array_length (ilgen->locals);
822 sigbuffer_init (&buf, 32);
823 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
824 idx = table->next_idx ++;
826 alloc_table (table, table->rows);
827 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
829 sigbuffer_add_value (&buf, 0x07);
830 sigbuffer_add_value (&buf, nl);
831 for (i = 0; i < nl; ++i) {
832 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
835 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
837 encode_reflection_type (assembly, lb->type, &buf);
839 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
840 sigbuffer_free (&buf);
842 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
848 method_count_clauses (MonoReflectionILGen *ilgen)
850 guint32 num_clauses = 0;
853 MonoILExceptionInfo *ex_info;
854 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
855 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
856 if (ex_info->handlers)
857 num_clauses += mono_array_length (ex_info->handlers);
865 static MonoExceptionClause*
866 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
868 MonoExceptionClause *clauses;
869 MonoExceptionClause *clause;
870 MonoILExceptionInfo *ex_info;
871 MonoILExceptionBlock *ex_block;
872 guint32 finally_start;
873 int i, j, clause_index;;
875 clauses = g_new0 (MonoExceptionClause, num_clauses);
878 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
879 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
880 finally_start = ex_info->start + ex_info->len;
881 if (!ex_info->handlers)
883 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
884 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
885 clause = &(clauses [clause_index]);
887 clause->flags = ex_block->type;
888 clause->try_offset = ex_info->start;
890 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
891 clause->try_len = finally_start - ex_info->start;
893 clause->try_len = ex_info->len;
894 clause->handler_offset = ex_block->start;
895 clause->handler_len = ex_block->len;
896 if (ex_block->extype) {
897 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
899 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
900 clause->data.filter_offset = ex_block->filter_offset;
902 clause->data.filter_offset = 0;
904 finally_start = ex_block->start + ex_block->len;
914 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
920 gint32 num_locals = 0;
921 gint32 num_exception = 0;
924 char fat_header [12];
927 guint32 local_sig = 0;
928 guint32 header_size = 12;
931 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
932 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
936 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
938 code = mb->ilgen->code;
939 code_size = mb->ilgen->code_len;
940 max_stack = mb->ilgen->max_stack;
941 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
942 if (mb->ilgen->ex_handlers)
943 num_exception = method_count_clauses (mb->ilgen);
947 char *name = mono_string_to_utf8 (mb->name);
948 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
949 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
952 mono_raise_exception (exception);
955 code_size = mono_array_length (code);
956 max_stack = 8; /* we probably need to run a verifier on the code... */
959 stream_data_align (&assembly->code);
961 /* check for exceptions, maxstack, locals */
962 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
964 if (code_size < 64 && !(code_size & 1)) {
965 flags = (code_size << 2) | 0x2;
966 } else if (code_size < 32 && (code_size & 1)) {
967 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
971 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
972 /* add to the fixup todo list */
973 if (mb->ilgen && mb->ilgen->num_token_fixups)
974 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
975 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
976 return assembly->text_rva + idx;
980 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
982 * FIXME: need to set also the header size in fat_flags.
983 * (and more sects and init locals flags)
987 fat_flags |= METHOD_HEADER_MORE_SECTS;
989 fat_flags |= METHOD_HEADER_INIT_LOCALS;
990 fat_header [0] = fat_flags;
991 fat_header [1] = (header_size / 4 ) << 4;
992 short_value = GUINT16_TO_LE (max_stack);
993 memcpy (fat_header + 2, &short_value, 2);
994 int_value = GUINT32_TO_LE (code_size);
995 memcpy (fat_header + 4, &int_value, 4);
996 int_value = GUINT32_TO_LE (local_sig);
997 memcpy (fat_header + 8, &int_value, 4);
998 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
999 /* add to the fixup todo list */
1000 if (mb->ilgen && mb->ilgen->num_token_fixups)
1001 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1003 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1004 if (num_exception) {
1005 unsigned char sheader [4];
1006 MonoILExceptionInfo * ex_info;
1007 MonoILExceptionBlock * ex_block;
1010 stream_data_align (&assembly->code);
1011 /* always use fat format for now */
1012 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1013 num_exception *= 6 * sizeof (guint32);
1014 num_exception += 4; /* include the size of the header */
1015 sheader [1] = num_exception & 0xff;
1016 sheader [2] = (num_exception >> 8) & 0xff;
1017 sheader [3] = (num_exception >> 16) & 0xff;
1018 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1019 /* fat header, so we are already aligned */
1021 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1022 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1023 if (ex_info->handlers) {
1024 int finally_start = ex_info->start + ex_info->len;
1025 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1027 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1029 val = GUINT32_TO_LE (ex_block->type);
1030 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1032 val = GUINT32_TO_LE (ex_info->start);
1033 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1034 /* need fault, too, probably */
1035 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1036 val = GUINT32_TO_LE (finally_start - ex_info->start);
1038 val = GUINT32_TO_LE (ex_info->len);
1039 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1040 /* handler offset */
1041 val = GUINT32_TO_LE (ex_block->start);
1042 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1044 val = GUINT32_TO_LE (ex_block->len);
1045 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1046 finally_start = ex_block->start + ex_block->len;
1047 if (ex_block->extype) {
1048 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1050 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1051 val = ex_block->filter_offset;
1055 val = GUINT32_TO_LE (val);
1056 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1057 /*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",
1058 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);*/
1061 g_error ("No clauses for ex info block %d", i);
1065 return assembly->text_rva + idx;
1069 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1072 MonoDynamicTable *table;
1075 table = &assembly->tables [table_idx];
1077 g_assert (col < table->columns);
1079 values = table->values + table->columns;
1080 for (i = 1; i <= table->rows; ++i) {
1081 if (values [col] == token)
1083 values += table->columns;
1088 /* protected by reflection_mutex:
1089 * maps a mono runtime reflection handle to MonoCustomAttrInfo*
1091 static GHashTable *dynamic_custom_attrs = NULL;
1093 static MonoCustomAttrInfo*
1094 lookup_custom_attr (void *member)
1096 MonoCustomAttrInfo *ainfo, *res;
1099 mono_reflection_lock ();
1100 ainfo = g_hash_table_lookup (dynamic_custom_attrs, member);
1101 mono_reflection_unlock ();
1104 /* Need to copy since it will be freed later */
1105 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
1106 res = g_malloc0 (size);
1107 memcpy (res, ainfo, size);
1114 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1116 /* FIXME: Need to do more checks */
1117 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1118 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1120 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1127 static MonoCustomAttrInfo*
1128 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1130 int i, index, count, not_visible;
1131 MonoCustomAttrInfo *ainfo;
1132 MonoReflectionCustomAttr *cattr;
1136 /* FIXME: check in assembly the Run flag is set */
1138 count = mono_array_length (cattrs);
1140 /* Skip nonpublic attributes since MS.NET seems to do the same */
1141 /* FIXME: This needs to be done more globally */
1143 for (i = 0; i < count; ++i) {
1144 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1145 if (!custom_attr_visible (image, cattr))
1148 count -= not_visible;
1150 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1152 ainfo->image = image;
1153 ainfo->num_attrs = count;
1155 mono_loader_lock ();
1156 for (i = 0; i < count; ++i) {
1157 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1158 if (custom_attr_visible (image, cattr)) {
1159 unsigned char *saved = mono_mempool_alloc (image->mempool, mono_array_length (cattr->data));
1160 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1161 ainfo->attrs [index].ctor = cattr->ctor->method;
1162 ainfo->attrs [index].data = saved;
1163 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1167 mono_loader_unlock ();
1173 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1175 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1180 mono_reflection_lock ();
1181 if (!dynamic_custom_attrs)
1182 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1184 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1185 ainfo->cached = TRUE;
1186 mono_reflection_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_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2352 const gchar *name, guint32 sig)
2354 MonoDynamicTable *table;
2358 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2360 if (assembly->save) {
2361 alloc_table (table, table->rows + 1);
2362 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2363 values [MONO_MEMBERREF_CLASS] = original;
2364 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2365 values [MONO_MEMBERREF_SIGNATURE] = sig;
2368 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2375 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2378 ReflectionMethodBuilder rmb;
2380 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2384 reflection_methodbuilder_from_method_builder (&rmb, mb);
2386 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2387 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2388 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2393 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2396 ReflectionMethodBuilder rmb;
2398 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2402 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2404 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2405 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2406 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2411 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2416 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2419 g_assert (f->field->parent);
2420 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2421 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2422 f->field->name, fieldref_encode_signature (assembly, type));
2423 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2428 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2433 MonoGenericClass *gclass;
2434 MonoDynamicGenericClass *dgclass;
2435 MonoReflectionFieldBuilder *fb = f->fb;
2438 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2441 klass = mono_class_from_mono_type (f->inst->type.type);
2442 gclass = f->inst->type.type->data.generic_class;
2443 g_assert (gclass->is_dynamic);
2444 dgclass = (MonoDynamicGenericClass *) gclass;
2446 name = mono_string_to_utf8 (fb->name);
2447 ftype = mono_class_inflate_generic_type (fb->type->type, mono_generic_class_get_context ((gclass)));
2448 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2449 fieldref_encode_signature (assembly, ftype));
2451 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2456 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2460 MonoGenericClass *gclass;
2461 MonoDynamicGenericClass *dgclass;
2462 MonoReflectionCtorBuilder *cb = c->cb;
2463 ReflectionMethodBuilder rmb;
2466 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2468 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2471 klass = mono_class_from_mono_type (c->inst->type.type);
2472 gclass = c->inst->type.type->data.generic_class;
2473 g_assert (gclass->is_dynamic);
2474 dgclass = (MonoDynamicGenericClass *) gclass;
2476 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2478 name = mono_string_to_utf8 (rmb.name);
2480 sig = method_builder_encode_signature (assembly, &rmb);
2482 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2485 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2490 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2494 MonoGenericClass *gclass;
2495 MonoDynamicGenericClass *dgclass;
2496 MonoReflectionMethodBuilder *mb = m->mb;
2497 ReflectionMethodBuilder rmb;
2500 if (create_methodspec && mb->generic_params)
2502 g_assert_not_reached ();
2504 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2507 klass = mono_class_from_mono_type (m->inst->type.type);
2508 gclass = m->inst->type.type->data.generic_class;
2509 g_assert (gclass->is_dynamic);
2510 dgclass = (MonoDynamicGenericClass *) gclass;
2512 reflection_methodbuilder_from_method_builder (&rmb, mb);
2514 name = mono_string_to_utf8 (rmb.name);
2516 sig = method_builder_encode_signature (assembly, &rmb);
2518 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2521 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2526 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2530 guint32 nparams = context->method_inst->type_argc;
2533 if (!assembly->save)
2536 sigbuffer_init (&buf, 32);
2538 * FIXME: vararg, explicit_this, differenc call_conv values...
2540 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2541 sigbuffer_add_value (&buf, nparams);
2543 for (i = 0; i < nparams; i++)
2544 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2546 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2547 sigbuffer_free (&buf);
2552 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2554 MonoDynamicTable *table;
2556 guint32 token, mtoken = 0, sig;
2557 MonoMethodInflated *imethod;
2558 MonoMethod *declaring;
2560 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2562 g_assert (method->is_inflated);
2563 imethod = (MonoMethodInflated *) method;
2564 declaring = imethod->declaring;
2566 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2567 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2569 if (!mono_method_signature (declaring)->generic_param_count)
2572 switch (mono_metadata_token_table (mtoken)) {
2573 case MONO_TABLE_MEMBERREF:
2574 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2576 case MONO_TABLE_METHOD:
2577 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2580 g_assert_not_reached ();
2583 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2585 if (assembly->save) {
2586 alloc_table (table, table->rows + 1);
2587 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2588 values [MONO_METHODSPEC_METHOD] = mtoken;
2589 values [MONO_METHODSPEC_SIGNATURE] = sig;
2592 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2599 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2601 MonoMethodInflated *imethod;
2604 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2608 g_assert (method->is_inflated);
2609 imethod = (MonoMethodInflated *) method;
2611 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2612 token = method_encode_methodspec (assembly, method);
2614 guint32 sig = method_encode_signature (
2615 assembly, mono_method_signature (imethod->declaring));
2616 token = mono_image_get_memberref_token (
2617 assembly, &method->klass->byval_arg, method->name, sig);
2620 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2625 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2627 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2630 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2631 token = mono_image_get_memberref_token (
2632 assembly, &m->klass->byval_arg, m->name, sig);
2638 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2640 MonoDynamicTable *table;
2648 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2649 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2650 * Because of this, we must not insert it into the `typeref' hash table.
2653 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2657 sigbuffer_init (&buf, 32);
2659 g_assert (tb->generic_params);
2660 klass = mono_class_from_mono_type (tb->type.type);
2662 if (tb->generic_container)
2663 mono_reflection_create_generic_class (tb);
2665 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2666 g_assert (klass->generic_container);
2667 sigbuffer_add_value (&buf, klass->byval_arg.type);
2668 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2670 count = mono_array_length (tb->generic_params);
2671 sigbuffer_add_value (&buf, count);
2672 for (i = 0; i < count; i++) {
2673 MonoReflectionGenericParam *gparam;
2675 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2677 encode_type (assembly, gparam->type.type, &buf);
2680 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2682 if (assembly->save) {
2683 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2684 alloc_table (table, table->rows + 1);
2685 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2686 values [MONO_TYPESPEC_SIGNATURE] = token;
2688 sigbuffer_free (&buf);
2690 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2691 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2697 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2699 MonoDynamicTable *table;
2702 guint32 token, pclass, parent, sig;
2705 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2709 klass = mono_class_from_mono_type (fb->typeb->type);
2710 name = mono_string_to_utf8 (fb->name);
2712 sig = fieldref_encode_signature (assembly, fb->type->type);
2714 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2715 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2717 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2718 parent >>= MONO_TYPEDEFORREF_BITS;
2720 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2722 if (assembly->save) {
2723 alloc_table (table, table->rows + 1);
2724 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2725 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2726 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2727 values [MONO_MEMBERREF_SIGNATURE] = sig;
2730 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2732 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2737 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2744 if (!assembly->save)
2747 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2748 g_assert (helper->type == 2);
2750 if (helper->arguments)
2751 nargs = mono_array_length (helper->arguments);
2755 size = 10 + (nargs * 10);
2757 sigbuffer_init (&buf, 32);
2759 /* Encode calling convention */
2760 /* Change Any to Standard */
2761 if ((helper->call_conv & 0x03) == 0x03)
2762 helper->call_conv = 0x01;
2763 /* explicit_this implies has_this */
2764 if (helper->call_conv & 0x40)
2765 helper->call_conv &= 0x20;
2767 if (helper->call_conv == 0) { /* Unmanaged */
2768 idx = helper->unmanaged_call_conv - 1;
2771 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2772 if (helper->call_conv & 0x02) /* varargs */
2776 sigbuffer_add_byte (&buf, idx);
2777 sigbuffer_add_value (&buf, nargs);
2778 encode_reflection_type (assembly, helper->return_type, &buf);
2779 for (i = 0; i < nargs; ++i) {
2780 MonoArray *modreqs = NULL;
2781 MonoArray *modopts = NULL;
2782 MonoReflectionType *pt;
2784 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
2785 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
2786 if (helper->modopts && (i < mono_array_length (helper->modopts)))
2787 modopts = mono_array_get (helper->modopts, MonoArray*, i);
2789 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
2790 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2791 encode_reflection_type (assembly, pt, &buf);
2793 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2794 sigbuffer_free (&buf);
2800 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2803 MonoDynamicTable *table;
2806 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2807 idx = table->next_idx ++;
2809 alloc_table (table, table->rows);
2810 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2812 values [MONO_STAND_ALONE_SIGNATURE] =
2813 mono_reflection_encode_sighelper (assembly, helper);
2819 reflection_cc_to_file (int call_conv) {
2820 switch (call_conv & 0x3) {
2822 case 1: return MONO_CALL_DEFAULT;
2823 case 2: return MONO_CALL_VARARG;
2825 g_assert_not_reached ();
2832 MonoMethodSignature *sig;
2838 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2843 MonoMethodSignature *sig;
2846 name = mono_string_to_utf8 (m->name);
2847 nparams = mono_array_length (m->parameters);
2848 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2850 sig->sentinelpos = -1;
2851 sig->call_convention = reflection_cc_to_file (m->call_conv);
2852 sig->param_count = nparams;
2853 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2854 for (i = 0; i < nparams; ++i) {
2855 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2856 sig->params [i] = t->type;
2859 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2861 if (strcmp (name, am->name) == 0 &&
2862 mono_metadata_type_equal (am->parent, m->parent->type) &&
2863 mono_metadata_signature_equal (am->sig, sig)) {
2866 m->table_idx = am->token & 0xffffff;
2870 am = g_new0 (ArrayMethod, 1);
2873 am->parent = m->parent->type;
2874 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2875 method_encode_signature (assembly, sig));
2876 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2877 m->table_idx = am->token & 0xffffff;
2882 * Insert into the metadata tables all the info about the TypeBuilder tb.
2883 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2886 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2888 MonoDynamicTable *table;
2890 int i, is_object = 0, is_system = 0;
2893 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2894 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2895 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2896 n = mono_string_to_utf8 (tb->name);
2897 if (strcmp (n, "Object") == 0)
2899 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2901 n = mono_string_to_utf8 (tb->nspace);
2902 if (strcmp (n, "System") == 0)
2904 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2906 if (tb->parent && !(is_system && is_object) &&
2907 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2908 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2910 values [MONO_TYPEDEF_EXTENDS] = 0;
2912 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2913 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2916 * if we have explicitlayout or sequentiallayouts, output data in the
2917 * ClassLayout table.
2919 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2920 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2921 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2923 alloc_table (table, table->rows);
2924 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2925 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2926 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2927 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2930 /* handle interfaces */
2931 if (tb->interfaces) {
2932 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2934 table->rows += mono_array_length (tb->interfaces);
2935 alloc_table (table, table->rows);
2936 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2937 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2938 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2939 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2940 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2941 values += MONO_INTERFACEIMPL_SIZE;
2947 table = &assembly->tables [MONO_TABLE_FIELD];
2948 table->rows += tb->num_fields;
2949 alloc_table (table, table->rows);
2950 for (i = 0; i < tb->num_fields; ++i)
2951 mono_image_get_field_info (
2952 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2955 /* handle constructors */
2957 table = &assembly->tables [MONO_TABLE_METHOD];
2958 table->rows += mono_array_length (tb->ctors);
2959 alloc_table (table, table->rows);
2960 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2961 mono_image_get_ctor_info (domain,
2962 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2965 /* handle methods */
2967 table = &assembly->tables [MONO_TABLE_METHOD];
2968 table->rows += tb->num_methods;
2969 alloc_table (table, table->rows);
2970 for (i = 0; i < tb->num_methods; ++i)
2971 mono_image_get_method_info (
2972 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2975 /* Do the same with properties etc.. */
2976 if (tb->events && mono_array_length (tb->events)) {
2977 table = &assembly->tables [MONO_TABLE_EVENT];
2978 table->rows += mono_array_length (tb->events);
2979 alloc_table (table, table->rows);
2980 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2982 alloc_table (table, table->rows);
2983 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2984 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2985 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2986 for (i = 0; i < mono_array_length (tb->events); ++i)
2987 mono_image_get_event_info (
2988 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2990 if (tb->properties && mono_array_length (tb->properties)) {
2991 table = &assembly->tables [MONO_TABLE_PROPERTY];
2992 table->rows += mono_array_length (tb->properties);
2993 alloc_table (table, table->rows);
2994 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2996 alloc_table (table, table->rows);
2997 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2998 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2999 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3000 for (i = 0; i < mono_array_length (tb->properties); ++i)
3001 mono_image_get_property_info (
3002 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3005 /* handle generic parameters */
3006 if (tb->generic_params) {
3007 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3008 table->rows += mono_array_length (tb->generic_params);
3009 alloc_table (table, table->rows);
3010 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3011 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3013 mono_image_get_generic_param_info (
3014 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3018 mono_image_add_decl_security (assembly,
3019 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3022 MonoDynamicTable *ntable;
3024 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3025 ntable->rows += mono_array_length (tb->subtypes);
3026 alloc_table (ntable, ntable->rows);
3027 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3029 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3030 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3032 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3033 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3034 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3035 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3036 mono_string_to_utf8 (tb->name), tb->table_idx,
3037 ntable->next_idx, ntable->rows);*/
3038 values += MONO_NESTED_CLASS_SIZE;
3045 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3049 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3051 if (!type->subtypes)
3054 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3055 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3056 collect_types (types, subtype);
3061 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3063 if ((*type1)->table_idx < (*type2)->table_idx)
3066 if ((*type1)->table_idx > (*type2)->table_idx)
3073 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3078 for (i = 0; i < mono_array_length (pinfo); ++i) {
3079 MonoReflectionParamBuilder *pb;
3080 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3083 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3088 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3091 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3093 for (i = 0; i < tb->num_fields; ++i) {
3094 MonoReflectionFieldBuilder* fb;
3095 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3096 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3100 for (i = 0; i < mono_array_length (tb->events); ++i) {
3101 MonoReflectionEventBuilder* eb;
3102 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3103 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3106 if (tb->properties) {
3107 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3108 MonoReflectionPropertyBuilder* pb;
3109 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3110 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3114 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3115 MonoReflectionCtorBuilder* cb;
3116 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3117 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3118 params_add_cattrs (assembly, cb->pinfo);
3123 for (i = 0; i < tb->num_methods; ++i) {
3124 MonoReflectionMethodBuilder* mb;
3125 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3126 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3127 params_add_cattrs (assembly, mb->pinfo);
3132 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3133 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3138 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3142 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3144 if (moduleb->global_methods) {
3145 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3146 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3147 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3148 params_add_cattrs (assembly, mb->pinfo);
3152 if (moduleb->global_fields) {
3153 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3154 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3155 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3159 if (moduleb->types) {
3160 for (i = 0; i < moduleb->num_types; ++i)
3161 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3166 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3168 MonoDynamicTable *table;
3172 char *b = blob_size;
3175 table = &assembly->tables [MONO_TABLE_FILE];
3177 alloc_table (table, table->rows);
3178 values = table->values + table->next_idx * MONO_FILE_SIZE;
3179 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3180 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3181 if (module->image->dynamic) {
3182 /* This depends on the fact that the main module is emitted last */
3183 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3184 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3187 path = g_strdup (module->image->name);
3189 mono_sha1_get_digest_from_file (path, hash);
3192 mono_metadata_encode_value (20, b, &b);
3193 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3194 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3199 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3201 MonoDynamicTable *table;
3204 table = &assembly->tables [MONO_TABLE_MODULE];
3205 mb->table_idx = table->next_idx ++;
3206 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3207 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3210 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3211 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3212 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3213 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3217 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3218 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3220 MonoDynamicTable *table;
3224 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3225 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3228 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3230 alloc_table (table, table->rows);
3231 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3233 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3234 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3235 if (klass->nested_in)
3236 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3238 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3239 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3240 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3242 res = table->next_idx;
3246 /* Emit nested types */
3247 if (klass->nested_classes) {
3250 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3251 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3258 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3259 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3264 klass = mono_class_from_mono_type (tb->type.type);
3266 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3268 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3269 parent_index, assembly);
3273 * We need to do this ourselves since klass->nested_classes is not set up.
3276 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3277 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3282 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3283 guint32 module_index, MonoDynamicImage *assembly)
3285 MonoImage *image = module->image;
3289 t = &image->tables [MONO_TABLE_TYPEDEF];
3291 for (i = 0; i < t->rows; ++i) {
3292 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3294 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3295 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3300 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3302 MonoDynamicTable *table;
3308 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3310 if (assemblyb->type_forwarders) {
3311 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3312 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3318 klass = mono_class_from_mono_type (t->type);
3320 scope = resolution_scope_from_image (assembly, klass->image);
3321 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3322 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3325 alloc_table (table, table->rows);
3326 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3328 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3329 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3330 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3331 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3332 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3337 #define align_pointer(base,p)\
3339 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3341 (p) += 4 - (__diff & 3);\
3345 compare_constants (const void *a, const void *b)
3347 const guint32 *a_values = a;
3348 const guint32 *b_values = b;
3349 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3353 compare_semantics (const void *a, const void *b)
3355 const guint32 *a_values = a;
3356 const guint32 *b_values = b;
3357 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3360 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3364 compare_custom_attrs (const void *a, const void *b)
3366 const guint32 *a_values = a;
3367 const guint32 *b_values = b;
3369 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3373 compare_field_marshal (const void *a, const void *b)
3375 const guint32 *a_values = a;
3376 const guint32 *b_values = b;
3378 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3382 compare_nested (const void *a, const void *b)
3384 const guint32 *a_values = a;
3385 const guint32 *b_values = b;
3387 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3391 compare_genericparam (const void *a, const void *b)
3393 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3394 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3396 if ((*b_entry)->owner == (*a_entry)->owner)
3398 (*a_entry)->gparam->type.type->data.generic_param->num -
3399 (*b_entry)->gparam->type.type->data.generic_param->num;
3401 return (*a_entry)->owner - (*b_entry)->owner;
3405 compare_declsecurity_attrs (const void *a, const void *b)
3407 const guint32 *a_values = a;
3408 const guint32 *b_values = b;
3410 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3414 pad_heap (MonoDynamicStream *sh)
3416 if (sh->index & 3) {
3417 int sz = 4 - (sh->index & 3);
3418 memset (sh->data + sh->index, 0, sz);
3425 MonoDynamicStream *stream;
3429 * build_compressed_metadata() fills in the blob of data that represents the
3430 * raw metadata as it will be saved in the PE file. The five streams are output
3431 * and the metadata tables are comnpressed from the guint32 array representation,
3432 * to the compressed on-disk format.
3435 build_compressed_metadata (MonoDynamicImage *assembly)
3437 MonoDynamicTable *table;
3439 guint64 valid_mask = 0;
3440 guint64 sorted_mask;
3441 guint32 heapt_size = 0;
3442 guint32 meta_size = 256; /* allow for header and other stuff */
3443 guint32 table_offset;
3444 guint32 ntables = 0;
3450 struct StreamDesc stream_desc [5];
3452 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3453 for (i = 0; i < assembly->gen_params->len; i++){
3454 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3455 write_generic_param_entry (assembly, entry);
3458 stream_desc [0].name = "#~";
3459 stream_desc [0].stream = &assembly->tstream;
3460 stream_desc [1].name = "#Strings";
3461 stream_desc [1].stream = &assembly->sheap;
3462 stream_desc [2].name = "#US";
3463 stream_desc [2].stream = &assembly->us;
3464 stream_desc [3].name = "#Blob";
3465 stream_desc [3].stream = &assembly->blob;
3466 stream_desc [4].name = "#GUID";
3467 stream_desc [4].stream = &assembly->guid;
3469 /* tables that are sorted */
3470 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3471 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3472 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3473 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3474 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3475 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3477 /* Compute table sizes */
3478 /* the MonoImage has already been created in mono_image_basic_init() */
3479 meta = &assembly->image;
3481 /* sizes should be multiple of 4 */
3482 pad_heap (&assembly->blob);
3483 pad_heap (&assembly->guid);
3484 pad_heap (&assembly->sheap);
3485 pad_heap (&assembly->us);
3487 /* Setup the info used by compute_sizes () */
3488 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3489 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3490 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3492 meta_size += assembly->blob.index;
3493 meta_size += assembly->guid.index;
3494 meta_size += assembly->sheap.index;
3495 meta_size += assembly->us.index;
3497 for (i=0; i < MONO_TABLE_NUM; ++i)
3498 meta->tables [i].rows = assembly->tables [i].rows;
3500 for (i = 0; i < MONO_TABLE_NUM; i++){
3501 if (meta->tables [i].rows == 0)
3503 valid_mask |= (guint64)1 << i;
3505 meta->tables [i].row_size = mono_metadata_compute_size (
3506 meta, i, &meta->tables [i].size_bitfield);
3507 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3509 heapt_size += 24; /* #~ header size */
3510 heapt_size += ntables * 4;
3511 /* make multiple of 4 */
3514 meta_size += heapt_size;
3515 meta->raw_metadata = g_malloc0 (meta_size);
3516 p = (unsigned char*)meta->raw_metadata;
3517 /* the metadata signature */
3518 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3519 /* version numbers and 4 bytes reserved */
3520 int16val = (guint16*)p;
3521 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3522 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3524 /* version string */
3525 int32val = (guint32*)p;
3526 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3528 memcpy (p, meta->version, strlen (meta->version));
3529 p += GUINT32_FROM_LE (*int32val);
3530 align_pointer (meta->raw_metadata, p);
3531 int16val = (guint16*)p;
3532 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3533 *int16val = GUINT16_TO_LE (5); /* number of streams */
3537 * write the stream info.
3539 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3540 table_offset += 3; table_offset &= ~3;
3542 assembly->tstream.index = heapt_size;
3543 for (i = 0; i < 5; ++i) {
3544 int32val = (guint32*)p;
3545 stream_desc [i].stream->offset = table_offset;
3546 *int32val++ = GUINT32_TO_LE (table_offset);
3547 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3548 table_offset += GUINT32_FROM_LE (*int32val);
3549 table_offset += 3; table_offset &= ~3;
3551 strcpy ((char*)p, stream_desc [i].name);
3552 p += strlen (stream_desc [i].name) + 1;
3553 align_pointer (meta->raw_metadata, p);
3556 * now copy the data, the table stream header and contents goes first.
3558 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3559 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3560 int32val = (guint32*)p;
3561 *int32val = GUINT32_TO_LE (0); /* reserved */
3564 if (mono_get_runtime_info ()->framework_version [0] > '1') {
3565 *p++ = 2; /* version */
3568 *p++ = 1; /* version */
3572 if (meta->idx_string_wide)
3574 if (meta->idx_guid_wide)
3576 if (meta->idx_blob_wide)
3579 *p++ = 1; /* reserved */
3580 int64val = (guint64*)p;
3581 *int64val++ = GUINT64_TO_LE (valid_mask);
3582 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3584 int32val = (guint32*)p;
3585 for (i = 0; i < MONO_TABLE_NUM; i++){
3586 if (meta->tables [i].rows == 0)
3588 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3590 p = (unsigned char*)int32val;
3592 /* sort the tables that still need sorting */
3593 table = &assembly->tables [MONO_TABLE_CONSTANT];
3595 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3596 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3598 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3599 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3601 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3602 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3604 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3605 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3607 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3608 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3609 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3611 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3613 /* compress the tables */
3614 for (i = 0; i < MONO_TABLE_NUM; i++){
3617 guint32 bitfield = meta->tables [i].size_bitfield;
3618 if (!meta->tables [i].rows)
3620 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3621 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3622 meta->tables [i].base = (char*)p;
3623 for (row = 1; row <= meta->tables [i].rows; ++row) {
3624 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3625 for (col = 0; col < assembly->tables [i].columns; ++col) {
3626 switch (mono_metadata_table_size (bitfield, col)) {
3628 *p++ = values [col];
3631 *p++ = values [col] & 0xff;
3632 *p++ = (values [col] >> 8) & 0xff;
3635 *p++ = values [col] & 0xff;
3636 *p++ = (values [col] >> 8) & 0xff;
3637 *p++ = (values [col] >> 16) & 0xff;
3638 *p++ = (values [col] >> 24) & 0xff;
3641 g_assert_not_reached ();
3645 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3648 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3649 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3650 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3651 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3652 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3654 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3658 * Some tables in metadata need to be sorted according to some criteria, but
3659 * when methods and fields are first created with reflection, they may be assigned a token
3660 * that doesn't correspond to the final token they will get assigned after the sorting.
3661 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3662 * with the reflection objects that represent them. Once all the tables are set up, the
3663 * reflection objects will contains the correct table index. fixup_method() will fixup the
3664 * tokens for the method with ILGenerator @ilgen.
3667 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3669 guint32 code_idx = GPOINTER_TO_UINT (value);
3670 MonoReflectionILTokenInfo *iltoken;
3671 MonoReflectionFieldBuilder *field;
3672 MonoReflectionCtorBuilder *ctor;
3673 MonoReflectionMethodBuilder *method;
3674 MonoReflectionTypeBuilder *tb;
3675 MonoReflectionArrayMethod *am;
3677 unsigned char *target;
3679 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3680 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3681 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3682 switch (target [3]) {
3683 case MONO_TABLE_FIELD:
3684 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3685 field = (MonoReflectionFieldBuilder *)iltoken->member;
3686 idx = field->table_idx;
3687 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3688 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3689 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3691 g_assert_not_reached ();
3694 case MONO_TABLE_METHOD:
3695 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3696 method = (MonoReflectionMethodBuilder *)iltoken->member;
3697 idx = method->table_idx;
3698 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3699 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3700 idx = ctor->table_idx;
3701 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3702 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3703 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3704 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3706 g_assert_not_reached ();
3709 case MONO_TABLE_TYPEDEF:
3710 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3711 g_assert_not_reached ();
3712 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3713 idx = tb->table_idx;
3715 case MONO_TABLE_MEMBERREF:
3716 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3717 am = (MonoReflectionArrayMethod*)iltoken->member;
3718 idx = am->table_idx;
3719 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3720 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3721 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3722 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3723 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3724 g_assert (m->klass->generic_class || m->klass->generic_container);
3726 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3728 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3729 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3730 g_assert (f->generic_info);
3732 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3733 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3735 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3737 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
3739 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
3742 g_assert_not_reached ();
3745 case MONO_TABLE_METHODSPEC:
3746 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3747 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3748 g_assert (mono_method_signature (m)->generic_param_count);
3751 g_assert_not_reached ();
3755 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3757 target [0] = idx & 0xff;
3758 target [1] = (idx >> 8) & 0xff;
3759 target [2] = (idx >> 16) & 0xff;
3766 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3767 * value is not known when the table is emitted.
3770 fixup_cattrs (MonoDynamicImage *assembly)
3772 MonoDynamicTable *table;
3774 guint32 type, i, idx, token;
3777 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3779 for (i = 0; i < table->rows; ++i) {
3780 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3782 type = values [MONO_CUSTOM_ATTR_TYPE];
3783 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3784 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3785 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3786 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3789 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3790 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3791 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3792 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3799 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3801 MonoDynamicTable *table;
3804 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3806 alloc_table (table, table->rows);
3807 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3808 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3809 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3810 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3811 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3816 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3818 MonoDynamicTable *table;
3822 char *b = blob_size;
3824 guint32 idx, offset;
3826 if (rsrc->filename) {
3827 name = mono_string_to_utf8 (rsrc->filename);
3828 sname = g_path_get_basename (name);
3830 table = &assembly->tables [MONO_TABLE_FILE];
3832 alloc_table (table, table->rows);
3833 values = table->values + table->next_idx * MONO_FILE_SIZE;
3834 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3835 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3838 mono_sha1_get_digest_from_file (name, hash);
3839 mono_metadata_encode_value (20, b, &b);
3840 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3841 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3843 idx = table->next_idx++;
3845 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3851 data = mono_array_addr (rsrc->data, char, 0);
3852 len = mono_array_length (rsrc->data);
3858 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3859 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3860 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3861 mono_image_add_stream_data (&assembly->resources, data, len);
3865 * The entry should be emitted into the MANIFESTRESOURCE table of
3866 * the main module, but that needs to reference the FILE table
3867 * which isn't emitted yet.
3874 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3878 set_version_from_string (MonoString *version, guint32 *values)
3880 gchar *ver, *p, *str;
3883 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3884 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3885 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3886 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3889 ver = str = mono_string_to_utf8 (version);
3890 for (i = 0; i < 4; ++i) {
3891 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3897 /* handle Revision and Build */
3907 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3911 char *b = blob_size;
3916 len = mono_array_length (pkey);
3917 mono_metadata_encode_value (len, b, &b);
3918 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3919 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
3921 assembly->public_key = g_malloc (len);
3922 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
3923 assembly->public_key_len = len;
3925 /* Special case: check for ECMA key (16 bytes) */
3926 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
3927 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3928 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3929 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3930 /* minimum key size (in 2.0) is 384 bits */
3931 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3933 /* FIXME - verifier */
3934 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3935 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3937 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3943 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3945 MonoDynamicTable *table;
3946 MonoDynamicImage *assembly;
3947 MonoReflectionAssemblyBuilder *assemblyb;
3951 guint32 module_index;
3953 assemblyb = moduleb->assemblyb;
3954 assembly = moduleb->dynamic_image;
3955 domain = mono_object_domain (assemblyb);
3957 /* Emit ASSEMBLY table */
3958 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3959 alloc_table (table, 1);
3960 values = table->values + MONO_ASSEMBLY_SIZE;
3961 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3962 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3963 if (assemblyb->culture) {
3964 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3966 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3968 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3969 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3970 set_version_from_string (assemblyb->version, values);
3972 /* Emit FILE + EXPORTED_TYPE table */
3974 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3976 MonoReflectionModuleBuilder *file_module =
3977 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3978 if (file_module != moduleb) {
3979 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3981 if (file_module->types) {
3982 for (j = 0; j < file_module->num_types; ++j) {
3983 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3984 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3989 if (assemblyb->loaded_modules) {
3990 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3991 MonoReflectionModule *file_module =
3992 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3993 mono_image_fill_file_table (domain, file_module, assembly);
3995 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3998 if (assemblyb->type_forwarders)
3999 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4001 /* Emit MANIFESTRESOURCE table */
4003 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4005 MonoReflectionModuleBuilder *file_module =
4006 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4007 /* The table for the main module is emitted later */
4008 if (file_module != moduleb) {
4010 if (file_module->resources) {
4011 int len = mono_array_length (file_module->resources);
4012 for (j = 0; j < len; ++j) {
4013 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4014 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4022 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4023 * for the modulebuilder @moduleb.
4024 * At the end of the process, method and field tokens are fixed up and the
4025 * on-disk compressed metadata representation is created.
4028 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4030 MonoDynamicTable *table;
4031 MonoDynamicImage *assembly;
4032 MonoReflectionAssemblyBuilder *assemblyb;
4038 assemblyb = moduleb->assemblyb;
4039 assembly = moduleb->dynamic_image;
4040 domain = mono_object_domain (assemblyb);
4042 if (assembly->text_rva)
4045 assembly->text_rva = START_TEXT_RVA;
4047 if (moduleb->is_main) {
4048 mono_image_emit_manifest (moduleb);
4051 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4052 table->rows = 1; /* .<Module> */
4054 alloc_table (table, table->rows);
4056 * Set the first entry.
4058 values = table->values + table->columns;
4059 values [MONO_TYPEDEF_FLAGS] = 0;
4060 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4061 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4062 values [MONO_TYPEDEF_EXTENDS] = 0;
4063 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4064 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4067 * handle global methods
4068 * FIXME: test what to do when global methods are defined in multiple modules.
4070 if (moduleb->global_methods) {
4071 table = &assembly->tables [MONO_TABLE_METHOD];
4072 table->rows += mono_array_length (moduleb->global_methods);
4073 alloc_table (table, table->rows);
4074 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4075 mono_image_get_method_info (
4076 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4078 if (moduleb->global_fields) {
4079 table = &assembly->tables [MONO_TABLE_FIELD];
4080 table->rows += mono_array_length (moduleb->global_fields);
4081 alloc_table (table, table->rows);
4082 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4083 mono_image_get_field_info (
4084 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4087 table = &assembly->tables [MONO_TABLE_MODULE];
4088 alloc_table (table, 1);
4089 mono_image_fill_module_table (domain, moduleb, assembly);
4091 /* Collect all types into a list sorted by their table_idx */
4092 types = g_ptr_array_new ();
4095 for (i = 0; i < moduleb->num_types; ++i) {
4096 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4097 collect_types (types, type);
4100 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4101 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4102 table->rows += types->len;
4103 alloc_table (table, table->rows);
4106 * Emit type names + namespaces at one place inside the string heap,
4107 * so load_class_names () needs to touch fewer pages.
4109 for (i = 0; i < types->len; ++i) {
4110 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4111 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4113 for (i = 0; i < types->len; ++i) {
4114 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4115 string_heap_insert_mstring (&assembly->sheap, tb->name);
4118 for (i = 0; i < types->len; ++i) {
4119 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4120 mono_image_get_type_info (domain, type, assembly);
4124 * table->rows is already set above and in mono_image_fill_module_table.
4126 /* add all the custom attributes at the end, once all the indexes are stable */
4127 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4129 /* CAS assembly permissions */
4130 if (assemblyb->permissions_minimum)
4131 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4132 if (assemblyb->permissions_optional)
4133 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4134 if (assemblyb->permissions_refused)
4135 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4137 module_add_cattrs (assembly, moduleb);
4140 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4142 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4143 * the final tokens and don't need another fixup pass. */
4145 if (moduleb->global_methods) {
4146 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4147 MonoReflectionMethodBuilder *mb = mono_array_get (
4148 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4149 mono_image_add_methodimpl (assembly, mb);
4153 for (i = 0; i < types->len; ++i) {
4154 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4155 if (type->methods) {
4156 for (j = 0; j < type->num_methods; ++j) {
4157 MonoReflectionMethodBuilder *mb = mono_array_get (
4158 type->methods, MonoReflectionMethodBuilder*, j);
4160 mono_image_add_methodimpl (assembly, mb);
4165 g_ptr_array_free (types, TRUE);
4167 fixup_cattrs (assembly);
4171 * mono_image_insert_string:
4172 * @module: module builder object
4175 * Insert @str into the user string stream of @module.
4178 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4180 MonoDynamicImage *assembly;
4185 MONO_ARCH_SAVE_REGS;
4187 if (!module->dynamic_image)
4188 mono_image_module_basic_init (module);
4190 assembly = module->dynamic_image;
4192 if (assembly->save) {
4193 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4194 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4195 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4197 char *swapped = g_malloc (2 * mono_string_length (str));
4198 const char *p = (const char*)mono_string_chars (str);
4200 swap_with_size (swapped, p, 2, mono_string_length (str));
4201 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4205 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4207 mono_image_add_stream_data (&assembly->us, "", 1);
4209 idx = assembly->us.index ++;
4212 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4214 return MONO_TOKEN_STRING | idx;
4218 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4223 klass = obj->vtable->klass;
4224 if (strcmp (klass->name, "MonoMethod") == 0) {
4225 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4226 MonoMethodSignature *sig, *old;
4227 guint32 sig_token, parent;
4230 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4232 nargs = mono_array_length (opt_param_types);
4233 old = mono_method_signature (method);
4234 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4236 sig->hasthis = old->hasthis;
4237 sig->explicit_this = old->explicit_this;
4238 sig->call_convention = old->call_convention;
4239 sig->generic_param_count = old->generic_param_count;
4240 sig->param_count = old->param_count + nargs;
4241 sig->sentinelpos = old->param_count;
4242 sig->ret = old->ret;
4244 for (i = 0; i < old->param_count; i++)
4245 sig->params [i] = old->params [i];
4247 for (i = 0; i < nargs; i++) {
4248 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4249 sig->params [old->param_count + i] = rt->type;
4252 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4253 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4254 parent >>= MONO_TYPEDEFORREF_BITS;
4256 parent <<= MONO_MEMBERREF_PARENT_BITS;
4257 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4259 sig_token = method_encode_signature (assembly, sig);
4260 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4261 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4262 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4263 ReflectionMethodBuilder rmb;
4264 guint32 parent, sig;
4266 reflection_methodbuilder_from_method_builder (&rmb, mb);
4267 rmb.opt_types = opt_param_types;
4269 sig = method_builder_encode_signature (assembly, &rmb);
4271 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4272 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4274 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4275 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4277 token = mono_image_get_varargs_method_token (
4278 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4280 g_error ("requested method token for %s\n", klass->name);
4287 * mono_image_create_token:
4288 * @assembly: a dynamic assembly
4290 * @register_token: Whenever to register the token in the assembly->tokens hash.
4292 * Get a token to insert in the IL code stream for the given MemberInfo.
4293 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4294 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4298 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4299 gboolean create_methodspec, gboolean register_token)
4304 klass = obj->vtable->klass;
4305 if (strcmp (klass->name, "MethodBuilder") == 0) {
4306 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4307 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4309 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4310 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4312 token = mono_image_get_methodbuilder_token (assembly, mb);
4313 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4314 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4315 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4316 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4318 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4319 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4321 token = mono_image_get_ctorbuilder_token (assembly, mb);
4322 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4323 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4324 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4325 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4326 if (tb->generic_params) {
4327 token = mono_image_get_generic_field_token (assembly, fb);
4329 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4331 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4332 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4333 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4334 } else if (strcmp (klass->name, "MonoType") == 0) {
4335 MonoReflectionType *tb = (MonoReflectionType *)obj;
4336 MonoClass *mc = mono_class_from_mono_type (tb->type);
4337 token = mono_metadata_token_from_dor (
4338 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4339 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4340 MonoReflectionType *tb = (MonoReflectionType *)obj;
4341 token = mono_metadata_token_from_dor (
4342 mono_image_typedef_or_ref (assembly, tb->type));
4343 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4344 MonoReflectionType *tb = (MonoReflectionType *)obj;
4345 token = mono_metadata_token_from_dor (
4346 mono_image_typedef_or_ref (assembly, tb->type));
4347 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4348 strcmp (klass->name, "MonoMethod") == 0 ||
4349 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4350 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4351 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4352 if (m->method->is_inflated) {
4353 if (create_methodspec)
4354 token = mono_image_get_methodspec_token (assembly, m->method);
4356 token = mono_image_get_inflated_method_token (assembly, m->method);
4357 } else if ((m->method->klass->image == &assembly->image) &&
4358 !m->method->klass->generic_class) {
4359 static guint32 method_table_idx = 0xffffff;
4360 if (m->method->klass->wastypebuilder) {
4361 /* we use the same token as the one that was assigned
4362 * to the Methodbuilder.
4363 * FIXME: do the equivalent for Fields.
4365 token = m->method->token;
4368 * Each token should have a unique index, but the indexes are
4369 * assigned by managed code, so we don't know about them. An
4370 * easy solution is to count backwards...
4372 method_table_idx --;
4373 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4376 token = mono_image_get_methodref_token (assembly, m->method);
4378 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4379 } else if (strcmp (klass->name, "MonoField") == 0) {
4380 MonoReflectionField *f = (MonoReflectionField *)obj;
4381 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4382 static guint32 field_table_idx = 0xffffff;
4384 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4386 token = mono_image_get_fieldref_token (assembly, f);
4388 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4389 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4390 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4391 token = mono_image_get_array_token (assembly, m);
4392 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4393 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4394 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4395 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4396 MonoReflectionType *tb = (MonoReflectionType *)obj;
4397 token = mono_metadata_token_from_dor (
4398 mono_image_typedef_or_ref (assembly, tb->type));
4399 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4400 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4401 token = mono_image_get_field_on_inst_token (assembly, f);
4402 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4403 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4404 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4405 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4406 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4407 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4409 g_error ("requested token for %s\n", klass->name);
4413 mono_image_register_token (assembly, token, obj);
4419 * mono_image_register_token:
4421 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4422 * the Module.ResolveXXXToken () methods to work.
4425 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4427 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4429 /* There could be multiple MethodInfo objects with the same token */
4430 //g_assert (prev == obj);
4432 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4437 guint32 import_lookup_table;
4441 guint32 import_address_table_rva;
4449 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4451 static MonoDynamicImage*
4452 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4454 static const guchar entrycode [16] = {0xff, 0x25, 0};
4455 MonoDynamicImage *image;
4458 const char *version = mono_get_runtime_info ()->runtime_version;
4461 image = GC_MALLOC (sizeof (MonoDynamicImage));
4463 image = g_new0 (MonoDynamicImage, 1);
4466 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4468 /*g_print ("created image %p\n", image);*/
4469 /* keep in sync with image.c */
4470 image->image.name = assembly_name;
4471 image->image.assembly_name = image->image.name; /* they may be different */
4472 image->image.module_name = module_name;
4473 image->image.version = g_strdup (version);
4474 image->image.md_version_major = 1;
4475 image->image.md_version_minor = 1;
4476 image->image.dynamic = TRUE;
4478 image->image.references = g_new0 (MonoAssembly*, 1);
4479 image->image.references [0] = NULL;
4481 mono_image_init (&image->image);
4483 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4484 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4485 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4486 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4487 image->handleref = g_hash_table_new (NULL, NULL);
4488 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4489 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4490 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4491 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4492 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4493 image->gen_params = g_ptr_array_new ();
4495 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4496 string_heap_init (&image->sheap);
4497 mono_image_add_stream_data (&image->us, "", 1);
4498 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4499 /* import tables... */
4500 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4501 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4502 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4503 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4504 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4505 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4506 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4507 stream_data_align (&image->code);
4509 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4511 for (i=0; i < MONO_TABLE_NUM; ++i) {
4512 image->tables [i].next_idx = 1;
4513 image->tables [i].columns = table_sizes [i];
4516 image->image.assembly = (MonoAssembly*)assembly;
4517 image->run = assembly->run;
4518 image->save = assembly->save;
4519 image->pe_kind = 0x1; /* ILOnly */
4520 image->machine = 0x14c; /* I386 */
4522 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4528 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4534 mono_dynamic_image_free (MonoDynamicImage *image)
4536 MonoDynamicImage *di = image;
4540 g_hash_table_destroy (di->typespec);
4542 g_hash_table_destroy (di->typeref);
4544 g_hash_table_destroy (di->handleref);
4546 mono_g_hash_table_destroy (di->tokens);
4547 if (di->generic_def_objects)
4548 mono_g_hash_table_destroy (di->generic_def_objects);
4549 if (di->blob_cache) {
4550 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4551 g_hash_table_destroy (di->blob_cache);
4553 g_list_free (di->array_methods);
4555 g_ptr_array_free (di->gen_params, TRUE);
4556 if (di->token_fixups)
4557 mono_g_hash_table_destroy (di->token_fixups);
4558 if (di->method_to_table_idx)
4559 g_hash_table_destroy (di->method_to_table_idx);
4560 if (di->field_to_table_idx)
4561 g_hash_table_destroy (di->field_to_table_idx);
4562 if (di->method_aux_hash)
4563 g_hash_table_destroy (di->method_aux_hash);
4564 g_free (di->strong_name);
4565 g_free (di->win32_res);
4566 /*g_print ("string heap destroy for image %p\n", di);*/
4567 mono_dynamic_stream_reset (&di->sheap);
4568 mono_dynamic_stream_reset (&di->code);
4569 mono_dynamic_stream_reset (&di->resources);
4570 mono_dynamic_stream_reset (&di->us);
4571 mono_dynamic_stream_reset (&di->blob);
4572 mono_dynamic_stream_reset (&di->tstream);
4573 mono_dynamic_stream_reset (&di->guid);
4574 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4575 g_free (di->tables [i].values);
4580 * mono_image_basic_init:
4581 * @assembly: an assembly builder object
4583 * Create the MonoImage that represents the assembly builder and setup some
4584 * of the helper hash table and the basic metadata streams.
4587 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4589 MonoDynamicAssembly *assembly;
4590 MonoDynamicImage *image;
4591 MonoDomain *domain = mono_object_domain (assemblyb);
4593 MONO_ARCH_SAVE_REGS;
4595 if (assemblyb->dynamic_assembly)
4599 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4601 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4604 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4606 assembly->assembly.ref_count = 1;
4607 assembly->assembly.dynamic = TRUE;
4608 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4609 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4610 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4611 if (assemblyb->culture)
4612 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4614 assembly->assembly.aname.culture = g_strdup ("");
4616 if (assemblyb->version) {
4617 char *vstr = mono_string_to_utf8 (assemblyb->version);
4618 char **version = g_strsplit (vstr, ".", 4);
4619 char **parts = version;
4620 assembly->assembly.aname.major = atoi (*parts++);
4621 assembly->assembly.aname.minor = atoi (*parts++);
4622 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4623 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4625 g_strfreev (version);
4628 assembly->assembly.aname.major = 0;
4629 assembly->assembly.aname.minor = 0;
4630 assembly->assembly.aname.build = 0;
4631 assembly->assembly.aname.revision = 0;
4634 assembly->run = assemblyb->access != 2;
4635 assembly->save = assemblyb->access != 1;
4637 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4638 image->initial_image = TRUE;
4639 assembly->assembly.aname.name = image->image.name;
4640 assembly->assembly.image = &image->image;
4642 mono_domain_assemblies_lock (domain);
4643 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4644 mono_domain_assemblies_unlock (domain);
4646 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4648 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4650 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4654 calc_section_size (MonoDynamicImage *assembly)
4658 /* alignment constraints */
4659 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4660 g_assert ((assembly->code.index % 4) == 0);
4661 assembly->meta_size += 3;
4662 assembly->meta_size &= ~3;
4663 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4664 g_assert ((assembly->resources.index % 4) == 0);
4666 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4667 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4670 if (assembly->win32_res) {
4671 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4673 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4674 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4678 assembly->sections [MONO_SECTION_RELOC].size = 12;
4679 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4689 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4693 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4695 ResTreeNode *t1 = (ResTreeNode*)a;
4696 ResTreeNode *t2 = (ResTreeNode*)b;
4698 return t1->id - t2->id;
4702 * resource_tree_create:
4704 * Organize the resources into a resource tree.
4706 static ResTreeNode *
4707 resource_tree_create (MonoArray *win32_resources)
4709 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4713 tree = g_new0 (ResTreeNode, 1);
4715 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4716 MonoReflectionWin32Resource *win32_res =
4717 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4721 /* FIXME: BUG: this stores managed references in unmanaged memory */
4722 lang_node = g_new0 (ResTreeNode, 1);
4723 lang_node->id = win32_res->lang_id;
4724 lang_node->win32_res = win32_res;
4726 /* Create type node if neccesary */
4728 for (l = tree->children; l; l = l->next)
4729 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4730 type_node = (ResTreeNode*)l->data;
4735 type_node = g_new0 (ResTreeNode, 1);
4736 type_node->id = win32_res->res_type;
4739 * The resource types have to be sorted otherwise
4740 * Windows Explorer can't display the version information.
4742 tree->children = g_slist_insert_sorted (tree->children,
4743 type_node, resource_tree_compare_by_id);
4746 /* Create res node if neccesary */
4748 for (l = type_node->children; l; l = l->next)
4749 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4750 res_node = (ResTreeNode*)l->data;
4755 res_node = g_new0 (ResTreeNode, 1);
4756 res_node->id = win32_res->res_id;
4757 type_node->children = g_slist_append (type_node->children, res_node);
4760 res_node->children = g_slist_append (res_node->children, lang_node);
4767 * resource_tree_encode:
4769 * Encode the resource tree into the format used in the PE file.
4772 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4775 MonoPEResourceDir dir;
4776 MonoPEResourceDirEntry dir_entry;
4777 MonoPEResourceDataEntry data_entry;
4781 * For the format of the resource directory, see the article
4782 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4786 memset (&dir, 0, sizeof (dir));
4787 memset (&dir_entry, 0, sizeof (dir_entry));
4788 memset (&data_entry, 0, sizeof (data_entry));
4790 g_assert (sizeof (dir) == 16);
4791 g_assert (sizeof (dir_entry) == 8);
4792 g_assert (sizeof (data_entry) == 16);
4794 node->offset = p - begin;
4796 /* IMAGE_RESOURCE_DIRECTORY */
4797 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4799 memcpy (p, &dir, sizeof (dir));
4802 /* Reserve space for entries */
4804 p += sizeof (dir_entry) * dir.res_id_entries;
4806 /* Write children */
4807 for (l = node->children; l; l = l->next) {
4808 ResTreeNode *child = (ResTreeNode*)l->data;
4810 if (child->win32_res) {
4812 child->offset = p - begin;
4814 /* IMAGE_RESOURCE_DATA_ENTRY */
4815 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4816 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4818 memcpy (p, &data_entry, sizeof (data_entry));
4819 p += sizeof (data_entry);
4821 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4822 p += data_entry.rde_size;
4824 resource_tree_encode (child, begin, p, &p);
4828 /* IMAGE_RESOURCE_ENTRY */
4829 for (l = node->children; l; l = l->next) {
4830 ResTreeNode *child = (ResTreeNode*)l->data;
4831 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4833 dir_entry.is_dir = child->win32_res ? 0 : 1;
4834 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4836 memcpy (entries, &dir_entry, sizeof (dir_entry));
4837 entries += sizeof (dir_entry);
4844 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4849 MonoReflectionWin32Resource *win32_res;
4852 if (!assemblyb->win32_resources)
4856 * Resources are stored in a three level tree inside the PE file.
4857 * - level one contains a node for each type of resource
4858 * - level two contains a node for each resource
4859 * - level three contains a node for each instance of a resource for a
4860 * specific language.
4863 tree = resource_tree_create (assemblyb->win32_resources);
4865 /* Estimate the size of the encoded tree */
4867 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4868 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4869 size += mono_array_length (win32_res->res_data);
4871 /* Directory structure */
4872 size += mono_array_length (assemblyb->win32_resources) * 256;
4873 p = buf = g_malloc (size);
4875 resource_tree_encode (tree, p, p, &p);
4877 g_assert (p - buf <= size);
4879 assembly->win32_res = g_malloc (p - buf);
4880 assembly->win32_res_size = p - buf;
4881 memcpy (assembly->win32_res, buf, p - buf);
4887 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4889 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4892 p += sizeof (MonoPEResourceDir);
4893 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4894 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4895 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4896 if (dir_entry->is_dir) {
4897 fixup_resource_directory (res_section, child, rva);
4899 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4900 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4903 p += sizeof (MonoPEResourceDirEntry);
4908 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4911 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4912 g_error ("WriteFile returned %d\n", GetLastError ());
4916 * mono_image_create_pefile:
4917 * @mb: a module builder object
4919 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4920 * assembly->pefile where it can be easily retrieved later in chunks.
4923 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4924 MonoMSDOSHeader *msdos;
4925 MonoDotNetHeader *header;
4926 MonoSectionTable *section;
4927 MonoCLIHeader *cli_header;
4928 guint32 size, image_size, virtual_base, text_offset;
4929 guint32 header_start, section_start, file_offset, virtual_offset;
4930 MonoDynamicImage *assembly;
4931 MonoReflectionAssemblyBuilder *assemblyb;
4932 MonoDynamicStream pefile_stream = {0};
4933 MonoDynamicStream *pefile = &pefile_stream;
4935 guint32 *rva, value;
4937 static const unsigned char msheader[] = {
4938 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4939 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4940 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4941 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4942 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4943 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4944 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4945 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4948 assemblyb = mb->assemblyb;
4950 mono_image_basic_init (assemblyb);
4951 assembly = mb->dynamic_image;
4953 assembly->pe_kind = assemblyb->pe_kind;
4954 assembly->machine = assemblyb->machine;
4955 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4956 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4958 mono_image_build_metadata (mb);
4960 if (mb->is_main && assemblyb->resources) {
4961 int len = mono_array_length (assemblyb->resources);
4962 for (i = 0; i < len; ++i)
4963 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4966 if (mb->resources) {
4967 int len = mono_array_length (mb->resources);
4968 for (i = 0; i < len; ++i)
4969 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4972 build_compressed_metadata (assembly);
4975 assembly_add_win32_resources (assembly, assemblyb);
4977 nsections = calc_section_size (assembly);
4979 /* The DOS header and stub */
4980 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4981 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
4983 /* the dotnet header */
4984 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4986 /* the section tables */
4987 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4989 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4990 virtual_offset = VIRT_ALIGN;
4993 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4994 if (!assembly->sections [i].size)
4997 file_offset += FILE_ALIGN - 1;
4998 file_offset &= ~(FILE_ALIGN - 1);
4999 virtual_offset += VIRT_ALIGN - 1;
5000 virtual_offset &= ~(VIRT_ALIGN - 1);
5002 assembly->sections [i].offset = file_offset;
5003 assembly->sections [i].rva = virtual_offset;
5005 file_offset += assembly->sections [i].size;
5006 virtual_offset += assembly->sections [i].size;
5007 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5010 file_offset += FILE_ALIGN - 1;
5011 file_offset &= ~(FILE_ALIGN - 1);
5013 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5015 /* back-patch info */
5016 msdos = (MonoMSDOSHeader*)pefile->data;
5017 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5019 header = (MonoDotNetHeader*)(pefile->data + header_start);
5020 header->pesig [0] = 'P';
5021 header->pesig [1] = 'E';
5023 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5024 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5025 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5026 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5027 if (assemblyb->pekind == 1) {
5029 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5032 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5035 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5037 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5038 header->pe.pe_major = 6;
5039 header->pe.pe_minor = 0;
5040 size = assembly->sections [MONO_SECTION_TEXT].size;
5041 size += FILE_ALIGN - 1;
5042 size &= ~(FILE_ALIGN - 1);
5043 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5044 size = assembly->sections [MONO_SECTION_RSRC].size;
5045 size += FILE_ALIGN - 1;
5046 size &= ~(FILE_ALIGN - 1);
5047 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5048 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5049 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5050 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5051 /* pe_rva_entry_point always at the beginning of the text section */
5052 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5054 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5055 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5056 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5057 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5058 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5059 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5060 size = section_start;
5061 size += FILE_ALIGN - 1;
5062 size &= ~(FILE_ALIGN - 1);
5063 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5065 size += VIRT_ALIGN - 1;
5066 size &= ~(VIRT_ALIGN - 1);
5067 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5070 // Translate the PEFileKind value to the value expected by the Windows loader
5076 // PEFileKinds.Dll == 1
5077 // PEFileKinds.ConsoleApplication == 2
5078 // PEFileKinds.WindowApplication == 3
5081 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5082 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5084 if (assemblyb->pekind == 3)
5089 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5091 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5092 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5093 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5094 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5095 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5096 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5098 /* fill data directory entries */
5100 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5101 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5103 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5104 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5106 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5107 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5108 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5109 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5110 /* patch entrypoint name */
5111 if (assemblyb->pekind == 1)
5112 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5114 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5115 /* patch imported function RVA name */
5116 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5117 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5119 /* the import table */
5120 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5121 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5122 /* patch imported dll RVA name and other entries in the dir */
5123 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5124 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5125 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5126 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5127 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5128 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5130 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5131 value = (assembly->text_rva + assembly->imp_names_offset);
5132 *p++ = (value) & 0xff;
5133 *p++ = (value >> 8) & (0xff);
5134 *p++ = (value >> 16) & (0xff);
5135 *p++ = (value >> 24) & (0xff);
5137 /* the CLI header info */
5138 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5139 cli_header->ch_size = GUINT32_FROM_LE (72);
5140 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5141 if (mono_get_runtime_info ()->framework_version [0] > '1')
5142 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5144 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5145 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5146 if (assemblyb->entry_point) {
5147 guint32 table_idx = 0;
5148 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5149 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5150 table_idx = methodb->table_idx;
5152 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5154 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5156 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5158 /* The embedded managed resources */
5159 text_offset = assembly->text_rva + assembly->code.index;
5160 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5161 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5162 text_offset += assembly->resources.index;
5163 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5164 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5165 text_offset += assembly->meta_size;
5166 if (assembly->strong_name_size) {
5167 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5168 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5169 text_offset += assembly->strong_name_size;
5172 /* write the section tables and section content */
5173 section = (MonoSectionTable*)(pefile->data + section_start);
5174 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5175 static const char section_names [][7] = {
5176 ".text", ".rsrc", ".reloc"
5178 if (!assembly->sections [i].size)
5180 strcpy (section->st_name, section_names [i]);
5181 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5182 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5183 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5184 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5185 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5186 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5187 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5191 checked_write_file (file, pefile->data, pefile->index);
5193 mono_dynamic_stream_reset (pefile);
5195 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5196 if (!assembly->sections [i].size)
5199 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5200 g_error ("SetFilePointer returned %d\n", GetLastError ());
5203 case MONO_SECTION_TEXT:
5204 /* patch entry point */
5205 p = (guchar*)(assembly->code.data + 2);
5206 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5207 *p++ = (value) & 0xff;
5208 *p++ = (value >> 8) & 0xff;
5209 *p++ = (value >> 16) & 0xff;
5210 *p++ = (value >> 24) & 0xff;
5212 checked_write_file (file, assembly->code.data, assembly->code.index);
5213 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5214 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5215 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5218 g_free (assembly->image.raw_metadata);
5220 case MONO_SECTION_RELOC: {
5224 guint16 type_and_offset;
5228 g_assert (sizeof (reloc) == 12);
5230 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5231 reloc.block_size = GUINT32_FROM_LE (12);
5234 * the entrypoint is always at the start of the text section
5235 * 3 is IMAGE_REL_BASED_HIGHLOW
5236 * 2 is patch_size_rva - text_rva
5238 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5241 checked_write_file (file, &reloc, sizeof (reloc));
5245 case MONO_SECTION_RSRC:
5246 if (assembly->win32_res) {
5248 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5249 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5250 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5254 g_assert_not_reached ();
5258 /* check that the file is properly padded */
5259 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5260 g_error ("SetFilePointer returned %d\n", GetLastError ());
5261 if (! SetEndOfFile (file))
5262 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5264 mono_dynamic_stream_reset (&assembly->code);
5265 mono_dynamic_stream_reset (&assembly->us);
5266 mono_dynamic_stream_reset (&assembly->blob);
5267 mono_dynamic_stream_reset (&assembly->guid);
5268 mono_dynamic_stream_reset (&assembly->sheap);
5270 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5271 g_hash_table_destroy (assembly->blob_cache);
5272 assembly->blob_cache = NULL;
5275 MonoReflectionModule *
5276 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5280 MonoImageOpenStatus status;
5281 MonoDynamicAssembly *assembly;
5282 guint32 module_count;
5283 MonoImage **new_modules;
5284 gboolean *new_modules_loaded;
5286 name = mono_string_to_utf8 (fileName);
5288 image = mono_image_open (name, &status);
5291 if (status == MONO_IMAGE_ERROR_ERRNO)
5292 exc = mono_get_exception_file_not_found (fileName);
5294 exc = mono_get_exception_bad_image_format (name);
5296 mono_raise_exception (exc);
5301 assembly = ab->dynamic_assembly;
5302 image->assembly = (MonoAssembly*)assembly;
5304 module_count = image->assembly->image->module_count;
5305 new_modules = g_new0 (MonoImage *, module_count + 1);
5306 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5308 if (image->assembly->image->modules)
5309 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5310 if (image->assembly->image->modules_loaded)
5311 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5312 new_modules [module_count] = image;
5313 new_modules_loaded [module_count] = TRUE;
5314 mono_image_addref (image);
5316 g_free (image->assembly->image->modules);
5317 image->assembly->image->modules = new_modules;
5318 image->assembly->image->modules_loaded = new_modules_loaded;
5319 image->assembly->image->module_count ++;
5321 mono_assembly_load_references (image, &status);
5323 mono_image_close (image);
5324 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5327 return mono_module_get_object (mono_domain_get (), image);
5331 * We need to return always the same object for MethodInfo, FieldInfo etc..
5332 * but we need to consider the reflected type.
5333 * type uses a different hash, since it uses custom hash/equal functions.
5338 MonoClass *refclass;
5342 reflected_equal (gconstpointer a, gconstpointer b) {
5343 const ReflectedEntry *ea = a;
5344 const ReflectedEntry *eb = b;
5346 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5350 reflected_hash (gconstpointer a) {
5351 const ReflectedEntry *ea = a;
5352 return mono_aligned_addr_hash (ea->item);
5355 #define CHECK_OBJECT(t,p,k) \
5361 mono_domain_lock (domain); \
5362 if (!domain->refobject_hash) \
5363 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5364 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5365 mono_domain_unlock (domain); \
5368 mono_domain_unlock (domain); \
5371 #ifndef HAVE_NULL_GC
5372 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5374 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5377 #define CACHE_OBJECT(t,p,o,k) \
5380 ReflectedEntry pe; \
5382 pe.refclass = (k); \
5383 mono_domain_lock (domain); \
5384 if (!domain->refobject_hash) \
5385 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5386 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5388 ReflectedEntry *e = ALLOC_REFENTRY; \
5390 e->refclass = (k); \
5391 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5394 mono_domain_unlock (domain); \
5399 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5401 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5405 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5407 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5411 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5413 MonoDynamicImage *image = moduleb->dynamic_image;
5414 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5417 MonoImage **new_modules;
5420 * FIXME: we already created an image in mono_image_basic_init (), but
5421 * we don't know which module it belongs to, since that is only
5422 * determined at assembly save time.
5424 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5425 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5427 moduleb->module.image = &image->image;
5428 moduleb->dynamic_image = image;
5429 register_module (mono_object_domain (moduleb), moduleb, image);
5431 /* register the module with the assembly */
5432 ass = ab->dynamic_assembly->assembly.image;
5433 module_count = ass->module_count;
5434 new_modules = g_new0 (MonoImage *, module_count + 1);
5437 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5438 new_modules [module_count] = &image->image;
5439 mono_image_addref (&image->image);
5441 g_free (ass->modules);
5442 ass->modules = new_modules;
5443 ass->module_count ++;
5448 * mono_assembly_get_object:
5449 * @domain: an app domain
5450 * @assembly: an assembly
5452 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5454 MonoReflectionAssembly*
5455 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5457 static MonoClass *System_Reflection_Assembly;
5458 MonoReflectionAssembly *res;
5460 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5461 if (!System_Reflection_Assembly)
5462 System_Reflection_Assembly = mono_class_from_name (
5463 mono_defaults.corlib, "System.Reflection", "Assembly");
5464 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5465 res->assembly = assembly;
5467 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5472 MonoReflectionModule*
5473 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5475 static MonoClass *System_Reflection_Module;
5476 MonoReflectionModule *res;
5479 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5480 if (!System_Reflection_Module)
5481 System_Reflection_Module = mono_class_from_name (
5482 mono_defaults.corlib, "System.Reflection", "Module");
5483 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5486 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5488 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5489 basename = g_path_get_basename (image->name);
5490 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5491 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5495 if (image->assembly->image == image) {
5496 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5500 if (image->assembly->image->modules) {
5501 for (i = 0; i < image->assembly->image->module_count; i++) {
5502 if (image->assembly->image->modules [i] == image)
5503 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5505 g_assert (res->token);
5509 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5512 MonoReflectionModule*
5513 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5515 static MonoClass *System_Reflection_Module;
5516 MonoReflectionModule *res;
5517 MonoTableInfo *table;
5518 guint32 cols [MONO_FILE_SIZE];
5520 guint32 i, name_idx;
5523 if (!System_Reflection_Module)
5524 System_Reflection_Module = mono_class_from_name (
5525 mono_defaults.corlib, "System.Reflection", "Module");
5526 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5528 table = &image->tables [MONO_TABLE_FILE];
5529 g_assert (table_index < table->rows);
5530 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5533 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5534 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5536 /* Check whenever the row has a corresponding row in the moduleref table */
5537 table = &image->tables [MONO_TABLE_MODULEREF];
5538 for (i = 0; i < table->rows; ++i) {
5539 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5540 val = mono_metadata_string_heap (image, name_idx);
5541 if (strcmp (val, name) == 0)
5542 res->image = image->modules [i];
5545 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5546 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5547 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5548 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5549 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5555 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5557 if ((t1->type != t2->type) ||
5558 (t1->byref != t2->byref))
5562 case MONO_TYPE_VOID:
5563 case MONO_TYPE_BOOLEAN:
5564 case MONO_TYPE_CHAR:
5575 case MONO_TYPE_STRING:
5578 case MONO_TYPE_OBJECT:
5579 case MONO_TYPE_TYPEDBYREF:
5581 case MONO_TYPE_VALUETYPE:
5582 case MONO_TYPE_CLASS:
5583 case MONO_TYPE_SZARRAY:
5584 return t1->data.klass == t2->data.klass;
5586 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5587 case MONO_TYPE_ARRAY:
5588 if (t1->data.array->rank != t2->data.array->rank)
5590 return t1->data.array->eklass == t2->data.array->eklass;
5591 case MONO_TYPE_GENERICINST: {
5593 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5594 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5595 if (i1->type_argc != i2->type_argc)
5597 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5598 &t2->data.generic_class->container_class->byval_arg))
5600 /* FIXME: we should probably just compare the instance pointers directly. */
5601 for (i = 0; i < i1->type_argc; ++i) {
5602 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5608 case MONO_TYPE_MVAR:
5609 return t1->data.generic_param == t2->data.generic_param;
5611 g_error ("implement type compare for %0x!", t1->type);
5619 mymono_metadata_type_hash (MonoType *t1)
5625 hash |= t1->byref << 6; /* do not collide with t1->type values */
5627 case MONO_TYPE_VALUETYPE:
5628 case MONO_TYPE_CLASS:
5629 case MONO_TYPE_SZARRAY:
5630 /* check if the distribution is good enough */
5631 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5633 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5634 case MONO_TYPE_GENERICINST: {
5636 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5637 hash += g_str_hash (t1->data.generic_class->container_class->name);
5639 for (i = 0; i < inst->type_argc; ++i) {
5640 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5649 static MonoReflectionGenericClass*
5650 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5652 static MonoClass *System_Reflection_MonoGenericClass;
5653 MonoReflectionGenericClass *res;
5654 MonoClass *klass, *gklass;
5656 if (!System_Reflection_MonoGenericClass) {
5657 System_Reflection_MonoGenericClass = mono_class_from_name (
5658 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5659 g_assert (System_Reflection_MonoGenericClass);
5662 klass = mono_class_from_mono_type (geninst);
5663 gklass = klass->generic_class->container_class;
5665 mono_class_init (klass);
5668 /* FIXME: allow unpinned later */
5669 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5671 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5674 res->type.type = geninst;
5675 g_assert (gklass->reflection_info);
5676 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
5677 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5683 verify_safe_for_managed_space (MonoType *type)
5685 switch (type->type) {
5687 case MONO_TYPE_ARRAY:
5688 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5690 return verify_safe_for_managed_space (type->data.type);
5691 case MONO_TYPE_SZARRAY:
5692 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5693 case MONO_TYPE_GENERICINST: {
5694 MonoGenericInst *inst = type->data.generic_class->inst;
5698 for (i = 0; i < inst->type_argc; ++i)
5699 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5705 case MONO_TYPE_MVAR:
5712 * mono_type_get_object:
5713 * @domain: an app domain
5716 * Return an System.MonoType object representing the type @type.
5719 mono_type_get_object (MonoDomain *domain, MonoType *type)
5721 MonoReflectionType *res;
5722 MonoClass *klass = mono_class_from_mono_type (type);
5724 /*we must avoid using @type as it might have come
5725 * from a mono_metadata_type_dup and the caller
5726 * expects that is can be freed.
5727 * Using the right type from
5729 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
5731 mono_domain_lock (domain);
5732 if (!domain->type_hash)
5733 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5734 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5735 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5736 mono_domain_unlock (domain);
5739 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
5740 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
5741 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5742 mono_g_hash_table_insert (domain->type_hash, type, res);
5743 mono_domain_unlock (domain);
5747 if (!verify_safe_for_managed_space (type)) {
5748 mono_domain_unlock (domain);
5749 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5752 if (klass->reflection_info && !klass->wastypebuilder) {
5753 /* g_assert_not_reached (); */
5754 /* should this be considered an error condition? */
5756 mono_domain_unlock (domain);
5757 return klass->reflection_info;
5760 // FIXME: Get rid of this, do it in the icalls for Type
5761 mono_class_init (klass);
5763 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5765 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5768 mono_g_hash_table_insert (domain->type_hash, type, res);
5769 mono_domain_unlock (domain);
5774 * mono_method_get_object:
5775 * @domain: an app domain
5777 * @refclass: the reflected type (can be NULL)
5779 * Return an System.Reflection.MonoMethod object representing the method @method.
5781 MonoReflectionMethod*
5782 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5785 * We use the same C representation for methods and constructors, but the type
5786 * name in C# is different.
5788 static MonoClass *System_Reflection_MonoMethod = NULL;
5789 static MonoClass *System_Reflection_MonoCMethod = NULL;
5790 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5791 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5793 MonoReflectionMethod *ret;
5795 if (method->is_inflated) {
5796 MonoReflectionGenericMethod *gret;
5798 refclass = method->klass;
5799 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5800 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5801 if (!System_Reflection_MonoGenericCMethod)
5802 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5803 klass = System_Reflection_MonoGenericCMethod;
5805 if (!System_Reflection_MonoGenericMethod)
5806 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5807 klass = System_Reflection_MonoGenericMethod;
5809 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5810 gret->method.method = method;
5811 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5812 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5813 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5817 refclass = method->klass;
5819 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5820 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5821 if (!System_Reflection_MonoCMethod)
5822 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5823 klass = System_Reflection_MonoCMethod;
5826 if (!System_Reflection_MonoMethod)
5827 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5828 klass = System_Reflection_MonoMethod;
5830 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5831 ret->method = method;
5832 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5833 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5837 * mono_field_get_object:
5838 * @domain: an app domain
5842 * Return an System.Reflection.MonoField object representing the field @field
5845 MonoReflectionField*
5846 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5848 MonoReflectionField *res;
5849 static MonoClass *monofield_klass;
5851 CHECK_OBJECT (MonoReflectionField *, field, klass);
5852 if (!monofield_klass)
5853 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5854 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
5857 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5858 if (field->generic_info)
5859 res->attrs = field->generic_info->generic_type->attrs;
5861 res->attrs = field->type->attrs;
5862 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5863 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5867 * mono_property_get_object:
5868 * @domain: an app domain
5870 * @property: a property
5872 * Return an System.Reflection.MonoProperty object representing the property @property
5875 MonoReflectionProperty*
5876 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5878 MonoReflectionProperty *res;
5879 static MonoClass *monoproperty_klass;
5881 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5882 if (!monoproperty_klass)
5883 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5884 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
5886 res->property = property;
5887 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5891 * mono_event_get_object:
5892 * @domain: an app domain
5896 * Return an System.Reflection.MonoEvent object representing the event @event
5899 MonoReflectionEvent*
5900 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5902 MonoReflectionEvent *res;
5903 static MonoClass *monoevent_klass;
5905 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5906 if (!monoevent_klass)
5907 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5908 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
5911 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5915 * mono_get_reflection_missing_object:
5916 * @domain: Domain where the object lives
5918 * Returns the System.Reflection.Missing.Value singleton object
5919 * (of type System.Reflection.Missing).
5921 * Used as the value for ParameterInfo.DefaultValue when Optional
5925 mono_get_reflection_missing_object (MonoDomain *domain)
5928 static MonoClassField *missing_value_field = NULL;
5930 if (!missing_value_field) {
5931 MonoClass *missing_klass;
5932 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
5933 mono_class_init (missing_klass);
5934 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
5935 g_assert (missing_value_field);
5937 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
5943 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
5946 *dbnull = mono_get_dbnull_object (domain);
5951 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
5953 if (!*reflection_missing)
5954 *reflection_missing = mono_get_reflection_missing_object (domain);
5955 return *reflection_missing;
5959 * mono_param_get_objects:
5960 * @domain: an app domain
5963 * Return an System.Reflection.ParameterInfo array object representing the parameters
5964 * in the method @method.
5967 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5969 static MonoClass *System_Reflection_ParameterInfo;
5970 MonoArray *res = NULL;
5971 MonoReflectionMethod *member = NULL;
5972 MonoReflectionParameter *param = NULL;
5973 char **names, **blobs = NULL;
5974 guint32 *types = NULL;
5975 MonoType *type = NULL;
5976 MonoObject *dbnull = NULL;
5977 MonoObject *missing = NULL;
5978 MonoMarshalSpec **mspecs;
5979 MonoMethodSignature *sig;
5982 if (!System_Reflection_ParameterInfo)
5983 System_Reflection_ParameterInfo = mono_class_from_name (
5984 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5986 if (!mono_method_signature (method)->param_count)
5987 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5989 /* Note: the cache is based on the address of the signature into the method
5990 * since we already cache MethodInfos with the method as keys.
5992 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5994 sig = mono_method_signature (method);
5995 member = mono_method_get_object (domain, method, NULL);
5996 names = g_new (char *, sig->param_count);
5997 mono_method_get_param_names (method, (const char **) names);
5999 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6000 mono_method_get_marshal_info (method, mspecs);
6002 res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
6003 for (i = 0; i < sig->param_count; ++i) {
6004 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
6005 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6006 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6007 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6008 param->PositionImpl = i;
6009 param->AttrsImpl = sig->params [i]->attrs;
6011 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6012 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6013 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6015 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6019 blobs = g_new0 (char *, sig->param_count);
6020 types = g_new0 (guint32, sig->param_count);
6021 get_default_param_value_blobs (method, blobs, types);
6024 /* Build MonoType for the type from the Constant Table */
6026 type = g_new0 (MonoType, 1);
6027 type->type = types [i];
6028 type->data.klass = NULL;
6029 if (types [i] == MONO_TYPE_CLASS)
6030 type->data.klass = mono_defaults.object_class;
6031 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6032 /* For enums, types [i] contains the base type */
6034 type->type = MONO_TYPE_VALUETYPE;
6035 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6037 type->data.klass = mono_class_from_mono_type (type);
6039 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6041 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6042 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6043 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6044 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6046 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6052 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6054 mono_array_setref (res, i, param);
6061 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6063 mono_metadata_free_marshal_spec (mspecs [i]);
6066 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6070 * mono_method_body_get_object:
6071 * @domain: an app domain
6074 * Return an System.Reflection.MethodBody object representing the method @method.
6076 MonoReflectionMethodBody*
6077 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6079 static MonoClass *System_Reflection_MethodBody = NULL;
6080 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6081 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6082 MonoReflectionMethodBody *ret;
6083 MonoMethodNormal *mn;
6084 MonoMethodHeader *header;
6085 guint32 method_rva, local_var_sig_token;
6087 unsigned char format, flags;
6090 if (!System_Reflection_MethodBody)
6091 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6092 if (!System_Reflection_LocalVariableInfo)
6093 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6094 if (!System_Reflection_ExceptionHandlingClause)
6095 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6097 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6099 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6100 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6101 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6102 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6104 mn = (MonoMethodNormal *)method;
6105 header = mono_method_get_header (method);
6107 /* Obtain local vars signature token */
6108 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6109 ptr = mono_image_rva_map (method->klass->image, method_rva);
6110 flags = *(const unsigned char *) ptr;
6111 format = flags & METHOD_HEADER_FORMAT_MASK;
6113 case METHOD_HEADER_TINY_FORMAT:
6114 case METHOD_HEADER_TINY_FORMAT1:
6115 local_var_sig_token = 0;
6117 case METHOD_HEADER_FAT_FORMAT:
6121 local_var_sig_token = read32 (ptr);
6124 g_assert_not_reached ();
6127 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6129 ret->init_locals = header->init_locals;
6130 ret->max_stack = header->max_stack;
6131 ret->local_var_sig_token = local_var_sig_token;
6132 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6133 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6136 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6137 for (i = 0; i < header->num_locals; ++i) {
6138 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6139 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6140 info->is_pinned = header->locals [i]->pinned;
6141 info->local_index = i;
6142 mono_array_setref (ret->locals, i, info);
6146 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6147 for (i = 0; i < header->num_clauses; ++i) {
6148 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6149 MonoExceptionClause *clause = &header->clauses [i];
6151 info->flags = clause->flags;
6152 info->try_offset = clause->try_offset;
6153 info->try_length = clause->try_len;
6154 info->handler_offset = clause->handler_offset;
6155 info->handler_length = clause->handler_len;
6156 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6157 info->filter_offset = clause->data.filter_offset;
6158 else if (clause->data.catch_class)
6159 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6161 mono_array_setref (ret->clauses, i, info);
6164 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6169 * mono_get_dbnull_object:
6170 * @domain: Domain where the object lives
6172 * Returns the System.DBNull.Value singleton object
6174 * Used as the value for ParameterInfo.DefaultValue
6177 mono_get_dbnull_object (MonoDomain *domain)
6180 static MonoClassField *dbnull_value_field = NULL;
6182 if (!dbnull_value_field) {
6183 MonoClass *dbnull_klass;
6184 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6185 mono_class_init (dbnull_klass);
6186 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6187 g_assert (dbnull_value_field);
6189 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6195 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6197 guint32 param_index, i, lastp, crow = 0;
6198 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6201 MonoClass *klass = method->klass;
6202 MonoImage *image = klass->image;
6203 MonoMethodSignature *methodsig = mono_method_signature (method);
6205 MonoTableInfo *constt;
6206 MonoTableInfo *methodt;
6207 MonoTableInfo *paramt;
6209 if (!methodsig->param_count)
6212 mono_class_init (klass);
6214 if (klass->image->dynamic) {
6215 MonoReflectionMethodAux *aux;
6216 if (method->is_inflated)
6217 method = ((MonoMethodInflated*)method)->declaring;
6218 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6219 if (aux && aux->param_defaults) {
6220 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6221 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6226 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6227 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6228 constt = &image->tables [MONO_TABLE_CONSTANT];
6230 idx = mono_method_get_index (method) - 1;
6231 g_assert (idx != -1);
6233 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6234 if (idx + 1 < methodt->rows)
6235 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6237 lastp = paramt->rows + 1;
6239 for (i = param_index; i < lastp; ++i) {
6242 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6243 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6245 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6248 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6253 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6254 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6255 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6262 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6267 MonoType *basetype = type;
6272 klass = mono_class_from_mono_type (type);
6273 if (klass->valuetype) {
6274 object = mono_object_new (domain, klass);
6275 retval = ((gchar *) object + sizeof (MonoObject));
6276 if (klass->enumtype)
6277 basetype = klass->enum_basetype;
6282 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6289 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6293 memset (assembly, 0, sizeof (MonoAssemblyName));
6295 assembly->culture = "";
6296 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6298 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6301 while (g_ascii_isspace (*p) || *p == ',') {
6310 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6312 assembly->major = strtoul (p, &s, 10);
6313 if (s == p || *s != '.')
6316 assembly->minor = strtoul (p, &s, 10);
6317 if (s == p || *s != '.')
6320 assembly->build = strtoul (p, &s, 10);
6321 if (s == p || *s != '.')
6324 assembly->revision = strtoul (p, &s, 10);
6328 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6330 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6331 assembly->culture = "";
6334 assembly->culture = p;
6335 while (*p && *p != ',') {
6339 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6341 if (strncmp (p, "null", 4) == 0) {
6346 while (*p && *p != ',') {
6349 len = (p - start + 1);
6350 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6351 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6352 g_strlcpy ((char*)assembly->public_key_token, start, len);
6355 while (*p && *p != ',')
6359 while (g_ascii_isspace (*p) || *p == ',') {
6373 * mono_reflection_parse_type:
6376 * Parse a type name as accepted by the GetType () method and output the info
6377 * extracted in the info structure.
6378 * the name param will be mangled, so, make a copy before passing it to this function.
6379 * The fields in info will be valid until the memory pointed to by name is valid.
6381 * See also mono_type_get_name () below.
6383 * Returns: 0 on parse error.
6386 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6387 MonoTypeNameParse *info)
6389 char *start, *p, *w, *temp, *last_point, *startn;
6390 int in_modifiers = 0;
6391 int isbyref = 0, rank, arity = 0, i;
6393 start = p = w = name;
6395 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6396 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6397 info->name = info->name_space = NULL;
6398 info->nested = NULL;
6399 info->modifiers = NULL;
6400 info->type_arguments = NULL;
6402 /* last_point separates the namespace from the name */
6408 *p = 0; /* NULL terminate the name */
6410 info->nested = g_list_append (info->nested, startn);
6411 /* we have parsed the nesting namespace + name */
6415 info->name_space = start;
6417 info->name = last_point + 1;
6419 info->name_space = (char *)"";
6438 i = strtol (p, &temp, 10);
6455 info->name_space = start;
6457 info->name = last_point + 1;
6459 info->name_space = (char *)"";
6466 if (isbyref) /* only one level allowed by the spec */
6469 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6473 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6479 info->type_arguments = g_ptr_array_new ();
6480 for (i = 0; i < arity; i++) {
6481 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6482 gboolean fqname = FALSE;
6484 g_ptr_array_add (info->type_arguments, subinfo);
6491 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6502 while (*p && (*p != ']'))
6510 if (g_ascii_isspace (*aname)) {
6517 !assembly_name_to_aname (&subinfo->assembly, aname))
6521 if (i + 1 < arity) {
6541 else if (*p == '*') /* '*' means unknown lower bound */
6542 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6549 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6560 if (g_ascii_isspace (*p)) {
6567 return 0; /* missing assembly name */
6568 if (!assembly_name_to_aname (&info->assembly, p))
6574 if (info->assembly.name)
6577 // *w = 0; /* terminate class name */
6579 if (!info->name || !*info->name)
6583 /* add other consistency checks */
6588 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6590 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6594 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6596 gboolean type_resolve = FALSE;
6598 MonoImage *rootimage = image;
6600 if (info->assembly.name) {
6601 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6603 /* then we must load the assembly ourselve - see #60439 */
6604 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6608 image = assembly->image;
6609 } else if (!image) {
6610 image = mono_defaults.corlib;
6613 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6614 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6615 image = mono_defaults.corlib;
6616 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6623 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6628 gboolean bounded = FALSE;
6631 image = mono_defaults.corlib;
6634 klass = mono_class_from_name_case (image, info->name_space, info->name);
6636 klass = mono_class_from_name (image, info->name_space, info->name);
6639 for (mod = info->nested; mod; mod = mod->next) {
6642 mono_class_init (klass);
6643 nested = klass->nested_classes;
6646 klass = nested->data;
6648 if (g_strcasecmp (klass->name, mod->data) == 0)
6651 if (strcmp (klass->name, mod->data) == 0)
6655 nested = nested->next;
6662 mono_class_init (klass);
6664 if (info->type_arguments) {
6665 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6666 MonoReflectionType *the_type;
6670 for (i = 0; i < info->type_arguments->len; i++) {
6671 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6673 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
6674 if (!type_args [i]) {
6680 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6682 instance = mono_reflection_bind_generic_parameters (
6683 the_type, info->type_arguments->len, type_args);
6689 klass = mono_class_from_mono_type (instance);
6692 for (mod = info->modifiers; mod; mod = mod->next) {
6693 modval = GPOINTER_TO_UINT (mod->data);
6694 if (!modval) { /* byref: must be last modifier */
6695 return &klass->this_arg;
6696 } else if (modval == -1) {
6697 klass = mono_ptr_class_get (&klass->byval_arg);
6698 } else if (modval == -2) {
6700 } else { /* array rank */
6701 klass = mono_bounded_array_class_get (klass, modval, bounded);
6703 mono_class_init (klass);
6706 return &klass->byval_arg;
6710 * mono_reflection_get_type:
6711 * @image: a metadata context
6712 * @info: type description structure
6713 * @ignorecase: flag for case-insensitive string compares
6714 * @type_resolve: whenever type resolve was already tried
6716 * Build a MonoType from the type description in @info.
6721 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
6722 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
6726 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
6728 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
6732 g_assert (assembly->dynamic);
6734 /* Enumerate all modules */
6737 if (abuilder->modules) {
6738 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6739 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6740 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
6746 if (!type && abuilder->loaded_modules) {
6747 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6748 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6749 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
6759 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6762 MonoReflectionAssembly *assembly;
6766 if (image && image->dynamic)
6767 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
6769 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
6772 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6779 *type_resolve = TRUE;
6782 /* Reconstruct the type name */
6783 fullName = g_string_new ("");
6784 if (info->name_space && (info->name_space [0] != '\0'))
6785 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6787 g_string_printf (fullName, info->name);
6788 for (mod = info->nested; mod; mod = mod->next)
6789 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6791 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6793 if (assembly->assembly->dynamic)
6794 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
6796 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
6799 g_string_free (fullName, TRUE);
6804 mono_reflection_free_type_info (MonoTypeNameParse *info)
6806 g_list_free (info->modifiers);
6807 g_list_free (info->nested);
6809 if (info->type_arguments) {
6812 for (i = 0; i < info->type_arguments->len; i++) {
6813 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6815 mono_reflection_free_type_info (subinfo);
6816 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
6820 g_ptr_array_free (info->type_arguments, TRUE);
6825 * mono_reflection_type_from_name:
6827 * @image: a metadata context (can be NULL).
6829 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6830 * it defaults to get the type from @image or, if @image is NULL or loading
6831 * from it fails, uses corlib.
6835 mono_reflection_type_from_name (char *name, MonoImage *image)
6837 MonoType *type = NULL;
6838 MonoTypeNameParse info;
6841 /* Make a copy since parse_type modifies its argument */
6842 tmp = g_strdup (name);
6844 /*g_print ("requested type %s\n", str);*/
6845 if (mono_reflection_parse_type (tmp, &info)) {
6846 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6850 mono_reflection_free_type_info (&info);
6855 * mono_reflection_get_token:
6857 * Return the metadata token of OBJ which should be an object
6858 * representing a metadata element.
6861 mono_reflection_get_token (MonoObject *obj)
6866 klass = obj->vtable->klass;
6868 if (strcmp (klass->name, "MethodBuilder") == 0) {
6869 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6871 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6872 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6873 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6875 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6876 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6877 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6879 /* Call mono_image_create_token so the object gets added to the tokens hash table */
6880 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
6881 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6882 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6883 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6884 } else if (strcmp (klass->name, "MonoType") == 0) {
6885 MonoReflectionType *tb = (MonoReflectionType *)obj;
6886 token = mono_class_from_mono_type (tb->type)->type_token;
6887 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6888 strcmp (klass->name, "MonoMethod") == 0 ||
6889 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6890 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6891 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6892 if (m->method->is_inflated) {
6893 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6894 return inflated->declaring->token;
6896 token = m->method->token;
6898 } else if (strcmp (klass->name, "MonoField") == 0) {
6899 MonoReflectionField *f = (MonoReflectionField*)obj;
6901 if (f->field->generic_info && f->field->generic_info->reflection_info)
6902 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6904 token = mono_class_get_field_token (f->field);
6905 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6906 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6908 token = mono_class_get_property_token (p->property);
6909 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6910 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6912 token = mono_class_get_event_token (p->event);
6913 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6914 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6916 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6917 } else if (strcmp (klass->name, "Module") == 0) {
6918 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6921 } else if (strcmp (klass->name, "Assembly") == 0) {
6922 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6924 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6925 MonoException *ex = mono_get_exception_not_implemented (msg);
6927 mono_raise_exception (ex);
6934 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6936 int slen, type = t->type;
6937 MonoClass *tklass = t->data.klass;
6943 case MONO_TYPE_BOOLEAN: {
6944 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6949 case MONO_TYPE_CHAR:
6951 case MONO_TYPE_I2: {
6952 guint16 *val = g_malloc (sizeof (guint16));
6957 #if SIZEOF_VOID_P == 4
6963 case MONO_TYPE_I4: {
6964 guint32 *val = g_malloc (sizeof (guint32));
6969 #if SIZEOF_VOID_P == 8
6970 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6974 case MONO_TYPE_I8: {
6975 guint64 *val = g_malloc (sizeof (guint64));
6980 case MONO_TYPE_R8: {
6981 double *val = g_malloc (sizeof (double));
6986 case MONO_TYPE_VALUETYPE:
6987 if (t->data.klass->enumtype) {
6988 type = t->data.klass->enum_basetype->type;
6991 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6994 case MONO_TYPE_STRING:
6995 if (*p == (char)0xFF) {
6999 slen = mono_metadata_decode_value (p, &p);
7001 return mono_string_new_len (mono_domain_get (), p, slen);
7002 case MONO_TYPE_CLASS: {
7005 if (*p == (char)0xFF) {
7010 slen = mono_metadata_decode_value (p, &p);
7011 n = g_memdup (p, slen + 1);
7013 t = mono_reflection_type_from_name (n, image);
7015 g_warning ("Cannot load type '%s'", n);
7019 return mono_type_get_object (mono_domain_get (), t);
7023 case MONO_TYPE_OBJECT: {
7026 MonoClass *subc = NULL;
7031 } else if (subt == 0x0E) {
7032 type = MONO_TYPE_STRING;
7034 } else if (subt == 0x1D) {
7035 MonoType simple_type = {{0}};
7040 /* See Partition II, Appendix B3 */
7041 etype = MONO_TYPE_OBJECT;
7042 type = MONO_TYPE_SZARRAY;
7043 simple_type.type = etype;
7044 tklass = mono_class_from_mono_type (&simple_type);
7046 } else if (subt == 0x55) {
7049 slen = mono_metadata_decode_value (p, &p);
7050 n = g_memdup (p, slen + 1);
7052 t = mono_reflection_type_from_name (n, image);
7054 g_error ("Cannot load type '%s'", n);
7057 subc = mono_class_from_mono_type (t);
7058 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7059 MonoType simple_type = {{0}};
7060 simple_type.type = subt;
7061 subc = mono_class_from_mono_type (&simple_type);
7063 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7065 val = load_cattr_value (image, &subc->byval_arg, p, end);
7066 obj = mono_object_new (mono_domain_get (), subc);
7067 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7071 case MONO_TYPE_SZARRAY: {
7073 guint32 i, alen, basetype;
7076 if (alen == 0xffffffff) {
7080 arr = mono_array_new (mono_domain_get(), tklass, alen);
7081 basetype = tklass->byval_arg.type;
7082 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7083 basetype = tklass->enum_basetype->type;
7088 case MONO_TYPE_BOOLEAN:
7089 for (i = 0; i < alen; i++) {
7090 MonoBoolean val = *p++;
7091 mono_array_set (arr, MonoBoolean, i, val);
7094 case MONO_TYPE_CHAR:
7097 for (i = 0; i < alen; i++) {
7098 guint16 val = read16 (p);
7099 mono_array_set (arr, guint16, i, val);
7106 for (i = 0; i < alen; i++) {
7107 guint32 val = read32 (p);
7108 mono_array_set (arr, guint32, i, val);
7113 for (i = 0; i < alen; i++) {
7116 mono_array_set (arr, double, i, val);
7122 for (i = 0; i < alen; i++) {
7123 guint64 val = read64 (p);
7124 mono_array_set (arr, guint64, i, val);
7128 case MONO_TYPE_CLASS:
7129 case MONO_TYPE_OBJECT:
7130 case MONO_TYPE_STRING:
7131 for (i = 0; i < alen; i++) {
7132 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7133 mono_array_setref (arr, i, item);
7137 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7143 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7149 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7151 static MonoClass *klass;
7152 static MonoMethod *ctor;
7154 void *params [2], *unboxed;
7157 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7159 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7161 params [0] = mono_type_get_object (mono_domain_get (), t);
7163 retval = mono_object_new (mono_domain_get (), klass);
7164 unboxed = mono_object_unbox (retval);
7165 mono_runtime_invoke (ctor, unboxed, params, NULL);
7171 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7173 static MonoClass *klass;
7174 static MonoMethod *ctor;
7176 void *unboxed, *params [2];
7179 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7181 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7184 params [1] = typedarg;
7185 retval = mono_object_new (mono_domain_get (), klass);
7186 unboxed = mono_object_unbox (retval);
7187 mono_runtime_invoke (ctor, unboxed, params, NULL);
7193 type_is_reference (MonoType *type)
7195 switch (type->type) {
7196 case MONO_TYPE_BOOLEAN:
7197 case MONO_TYPE_CHAR:
7210 case MONO_TYPE_VALUETYPE:
7218 free_param_data (MonoMethodSignature *sig, void **params) {
7220 for (i = 0; i < sig->param_count; ++i) {
7221 if (!type_is_reference (sig->params [i]))
7222 g_free (params [i]);
7227 * Find the field index in the metadata FieldDef table.
7230 find_field_index (MonoClass *klass, MonoClassField *field) {
7233 for (i = 0; i < klass->field.count; ++i) {
7234 if (field == &klass->fields [i])
7235 return klass->field.first + 1 + i;
7241 * Find the property index in the metadata Property table.
7244 find_property_index (MonoClass *klass, MonoProperty *property) {
7247 for (i = 0; i < klass->property.count; ++i) {
7248 if (property == &klass->properties [i])
7249 return klass->property.first + 1 + i;
7255 * Find the event index in the metadata Event table.
7258 find_event_index (MonoClass *klass, MonoEvent *event) {
7261 for (i = 0; i < klass->event.count; ++i) {
7262 if (event == &klass->events [i])
7263 return klass->event.first + 1 + i;
7269 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7271 const char *p = (const char*)data;
7273 guint32 i, j, num_named;
7277 mono_class_init (method->klass);
7280 attr = mono_object_new (mono_domain_get (), method->klass);
7281 mono_runtime_invoke (method, attr, NULL, NULL);
7285 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7288 /*g_print ("got attr %s\n", method->klass->name);*/
7290 /* Allocate using alloca so it gets GC tracking */
7291 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7295 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7296 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7300 attr = mono_object_new (mono_domain_get (), method->klass);
7301 mono_runtime_invoke (method, attr, params, NULL);
7302 free_param_data (method->signature, params);
7303 num_named = read16 (named);
7305 for (j = 0; j < num_named; j++) {
7307 char *name, named_type, data_type;
7308 named_type = *named++;
7309 data_type = *named++; /* type of data */
7310 if (data_type == MONO_TYPE_SZARRAY)
7311 data_type = *named++;
7312 if (data_type == MONO_TYPE_ENUM) {
7315 type_len = mono_metadata_decode_blob_size (named, &named);
7316 type_name = g_malloc (type_len + 1);
7317 memcpy (type_name, named, type_len);
7318 type_name [type_len] = 0;
7320 /* FIXME: lookup the type and check type consistency */
7323 name_len = mono_metadata_decode_blob_size (named, &named);
7324 name = g_malloc (name_len + 1);
7325 memcpy (name, named, name_len);
7326 name [name_len] = 0;
7328 if (named_type == 0x53) {
7329 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7330 void *val = load_cattr_value (image, field->type, named, &named);
7331 mono_field_set_value (attr, field, val);
7332 if (!type_is_reference (field->type))
7334 } else if (named_type == 0x54) {
7337 MonoType *prop_type;
7339 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7340 /* can we have more that 1 arg in a custom attr named property? */
7341 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7342 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7343 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7344 mono_property_set_value (prop, attr, pparams, NULL);
7345 if (!type_is_reference (prop_type))
7346 g_free (pparams [0]);
7355 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7357 MonoArray *typedargs, *namedargs;
7358 MonoClass *attrklass;
7359 static MonoMethod *ctor;
7362 const char *p = (const char*)data;
7364 guint32 i, j, num_named;
7367 mono_class_init (method->klass);
7370 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7372 domain = mono_domain_get ();
7374 /* This is for Attributes with no parameters */
7375 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7376 params [0] = mono_method_get_object (domain, method, NULL);
7377 params [1] = params [2] = NULL;
7378 mono_runtime_invoke (method, attr, params, NULL);
7382 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7385 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7389 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7390 MonoObject *obj, *typedarg;
7393 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7394 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7395 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7396 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7397 mono_array_setref (typedargs, i, typedarg);
7399 if (!type_is_reference (mono_method_signature (method)->params [i]))
7404 num_named = read16 (named);
7405 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7407 attrklass = method->klass;
7408 for (j = 0; j < num_named; j++) {
7410 char *name, named_type, data_type;
7411 named_type = *named++;
7412 data_type = *named++; /* type of data */
7413 if (data_type == MONO_TYPE_SZARRAY)
7414 data_type = *named++;
7415 if (data_type == MONO_TYPE_ENUM) {
7418 type_len = mono_metadata_decode_blob_size (named, &named);
7419 type_name = g_malloc (type_len + 1);
7420 memcpy (type_name, named, type_len);
7421 type_name [type_len] = 0;
7423 /* FIXME: lookup the type and check type consistency */
7426 name_len = mono_metadata_decode_blob_size (named, &named);
7427 name = g_malloc (name_len + 1);
7428 memcpy (name, named, name_len);
7429 name [name_len] = 0;
7431 if (named_type == 0x53) {
7432 MonoObject *obj, *typedarg, *namedarg;
7433 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7434 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7436 minfo = mono_field_get_object (domain, NULL, field);
7437 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7438 typedarg = create_cattr_typed_arg (field->type, obj);
7439 namedarg = create_cattr_named_arg (minfo, typedarg);
7440 mono_array_setref (namedargs, j, namedarg);
7441 if (!type_is_reference (field->type))
7443 } else if (named_type == 0x54) {
7444 MonoObject *obj, *typedarg, *namedarg;
7445 MonoType *prop_type;
7447 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7449 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7450 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7451 minfo = mono_property_get_object (domain, NULL, prop);
7452 val = load_cattr_value (image, prop_type, named, &named);
7453 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7454 typedarg = create_cattr_typed_arg (prop_type, obj);
7455 namedarg = create_cattr_named_arg (minfo, typedarg);
7456 mono_array_setref (namedargs, j, namedarg);
7457 if (!type_is_reference (prop_type))
7462 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7463 params [0] = mono_method_get_object (domain, method, NULL);
7464 params [1] = typedargs;
7465 params [2] = namedargs;
7466 mono_runtime_invoke (ctor, attr, params, NULL);
7471 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7477 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7478 for (i = 0; i < cinfo->num_attrs; ++i) {
7479 if (!cinfo->attrs [i].ctor)
7480 /* The cattr type is not finished yet */
7481 /* We should include the type name but cinfo doesn't contain it */
7482 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7483 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7484 mono_array_setref (result, i, attr);
7490 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7497 for (i = 0; i < cinfo->num_attrs; ++i) {
7498 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7502 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7504 for (i = 0; i < cinfo->num_attrs; ++i) {
7505 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7506 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7507 mono_array_setref (result, n, attr);
7515 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7521 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7522 for (i = 0; i < cinfo->num_attrs; ++i) {
7523 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7524 mono_array_setref (result, i, attr);
7530 * mono_custom_attrs_from_index:
7532 * Returns: NULL if no attributes are found or if a loading error occurs.
7535 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7537 guint32 mtoken, i, len;
7538 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7540 MonoCustomAttrInfo *ainfo;
7541 GList *tmp, *list = NULL;
7544 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7546 i = mono_metadata_custom_attrs_from_index (image, idx);
7550 while (i < ca->rows) {
7551 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7553 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7556 len = g_list_length (list);
7559 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7560 ainfo->num_attrs = len;
7561 ainfo->image = image;
7562 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7563 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7564 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7565 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7566 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7567 mtoken |= MONO_TOKEN_METHOD_DEF;
7569 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7570 mtoken |= MONO_TOKEN_MEMBER_REF;
7573 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7576 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7577 if (!ainfo->attrs [i].ctor) {
7578 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7583 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7584 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7585 ainfo->attrs [i].data = (guchar*)data;
7593 mono_custom_attrs_from_method (MonoMethod *method)
7595 MonoCustomAttrInfo *cinfo;
7599 * An instantiated method has the same cattrs as the generic method definition.
7601 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7602 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7604 if (method->is_inflated)
7605 method = ((MonoMethodInflated *) method)->declaring;
7607 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (method)))
7609 idx = mono_method_get_index (method);
7610 idx <<= MONO_CUSTOM_ATTR_BITS;
7611 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7612 return mono_custom_attrs_from_index (method->klass->image, idx);
7616 mono_custom_attrs_from_class (MonoClass *klass)
7618 MonoCustomAttrInfo *cinfo;
7621 if (klass->generic_class)
7622 klass = klass->generic_class->container_class;
7624 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (klass)))
7626 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
7627 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
7628 idx <<= MONO_CUSTOM_ATTR_BITS;
7629 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
7631 idx = mono_metadata_token_index (klass->type_token);
7632 idx <<= MONO_CUSTOM_ATTR_BITS;
7633 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7635 return mono_custom_attrs_from_index (klass->image, idx);
7639 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7641 MonoCustomAttrInfo *cinfo;
7644 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (assembly)))
7646 idx = 1; /* there is only one assembly */
7647 idx <<= MONO_CUSTOM_ATTR_BITS;
7648 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7649 return mono_custom_attrs_from_index (assembly->image, idx);
7652 static MonoCustomAttrInfo*
7653 mono_custom_attrs_from_module (MonoImage *image)
7655 MonoCustomAttrInfo *cinfo;
7658 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (image)))
7660 idx = 1; /* there is only one module */
7661 idx <<= MONO_CUSTOM_ATTR_BITS;
7662 idx |= MONO_CUSTOM_ATTR_MODULE;
7663 return mono_custom_attrs_from_index (image, idx);
7667 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7669 MonoCustomAttrInfo *cinfo;
7672 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (property)))
7674 idx = find_property_index (klass, property);
7675 idx <<= MONO_CUSTOM_ATTR_BITS;
7676 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7677 return mono_custom_attrs_from_index (klass->image, idx);
7681 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7683 MonoCustomAttrInfo *cinfo;
7686 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (event)))
7688 idx = find_event_index (klass, event);
7689 idx <<= MONO_CUSTOM_ATTR_BITS;
7690 idx |= MONO_CUSTOM_ATTR_EVENT;
7691 return mono_custom_attrs_from_index (klass->image, idx);
7695 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7697 MonoCustomAttrInfo *cinfo;
7700 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (field)))
7702 idx = find_field_index (klass, field);
7703 idx <<= MONO_CUSTOM_ATTR_BITS;
7704 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7705 return mono_custom_attrs_from_index (klass->image, idx);
7709 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7712 guint32 i, idx, method_index;
7713 guint32 param_list, param_last, param_pos, found;
7715 MonoReflectionMethodAux *aux;
7718 * An instantiated method has the same cattrs as the generic method definition.
7720 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7721 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7723 if (method->is_inflated)
7724 method = ((MonoMethodInflated *) method)->declaring;
7726 if (method->klass->image->dynamic) {
7727 MonoCustomAttrInfo *res, *ainfo;
7730 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7731 if (!aux || !aux->param_cattr)
7734 /* Need to copy since it will be freed later */
7735 ainfo = aux->param_cattr [param];
7736 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7737 res = g_malloc0 (size);
7738 memcpy (res, ainfo, size);
7742 image = method->klass->image;
7743 method_index = mono_method_get_index (method);
7744 ca = &image->tables [MONO_TABLE_METHOD];
7746 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7747 if (method_index == ca->rows) {
7748 ca = &image->tables [MONO_TABLE_PARAM];
7749 param_last = ca->rows + 1;
7751 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7752 ca = &image->tables [MONO_TABLE_PARAM];
7755 for (i = param_list; i < param_last; ++i) {
7756 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7757 if (param_pos == param) {
7765 idx <<= MONO_CUSTOM_ATTR_BITS;
7766 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7767 return mono_custom_attrs_from_index (image, idx);
7771 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7775 for (i = 0; i < ainfo->num_attrs; ++i) {
7776 klass = ainfo->attrs [i].ctor->klass;
7777 if (mono_class_has_parent (klass, attr_klass))
7784 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7791 for (i = 0; i < ainfo->num_attrs; ++i) {
7792 klass = ainfo->attrs [i].ctor->klass;
7793 if (mono_class_has_parent (klass, attr_klass)) {
7798 if (attr_index == -1)
7801 attrs = mono_custom_attrs_construct (ainfo);
7803 return mono_array_get (attrs, MonoObject*, attr_index);
7809 * mono_reflection_get_custom_attrs_info:
7810 * @obj: a reflection object handle
7812 * Return the custom attribute info for attributes defined for the
7813 * reflection handle @obj. The objects.
7816 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7819 MonoCustomAttrInfo *cinfo = NULL;
7821 klass = obj->vtable->klass;
7822 if (klass == mono_defaults.monotype_class) {
7823 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7824 klass = mono_class_from_mono_type (rtype->type);
7825 cinfo = mono_custom_attrs_from_class (klass);
7826 } else if (strcmp ("Assembly", klass->name) == 0) {
7827 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7828 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7829 } else if (strcmp ("Module", klass->name) == 0) {
7830 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7831 cinfo = mono_custom_attrs_from_module (module->image);
7832 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7833 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7834 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7835 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7836 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7837 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7838 } else if (strcmp ("MonoField", klass->name) == 0) {
7839 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7840 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7841 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7842 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7843 cinfo = mono_custom_attrs_from_method (rmethod->method);
7844 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7845 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7846 cinfo = mono_custom_attrs_from_method (rmethod->method);
7847 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7848 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7849 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7850 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7851 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7852 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7853 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7854 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7855 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7856 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7857 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7858 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7859 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7860 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7861 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7862 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7863 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7864 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7865 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7866 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7867 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7868 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7869 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
7870 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
7871 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
7872 } else { /* handle other types here... */
7873 g_error ("get custom attrs not yet supported for %s", klass->name);
7880 * mono_reflection_get_custom_attrs_by_type:
7881 * @obj: a reflection object handle
7883 * Return an array with all the custom attributes defined of the
7884 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7885 * of that type are returned. The objects are fully build. Return NULL if a loading error
7889 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7892 MonoCustomAttrInfo *cinfo;
7894 cinfo = mono_reflection_get_custom_attrs_info (obj);
7897 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7899 result = mono_custom_attrs_construct (cinfo);
7901 mono_custom_attrs_free (cinfo);
7903 if (mono_loader_get_last_error ())
7905 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
7912 * mono_reflection_get_custom_attrs:
7913 * @obj: a reflection object handle
7915 * Return an array with all the custom attributes defined of the
7916 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
7920 mono_reflection_get_custom_attrs (MonoObject *obj)
7922 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7926 * mono_reflection_get_custom_attrs_data:
7927 * @obj: a reflection obj handle
7929 * Returns an array of System.Reflection.CustomAttributeData,
7930 * which include information about attributes reflected on
7931 * types loaded using the Reflection Only methods
7934 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7937 MonoCustomAttrInfo *cinfo;
7939 cinfo = mono_reflection_get_custom_attrs_info (obj);
7941 result = mono_custom_attrs_data_construct (cinfo);
7943 mono_custom_attrs_free (cinfo);
7945 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
7950 static MonoReflectionType*
7951 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
7953 MonoMethod *method_get_underlying_system_type;
7955 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
7956 mono_class_get_method_from_name (mono_object_class (t),
7957 "get_UnderlyingSystemType",
7959 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
7963 mono_reflection_type_get_handle (MonoReflectionType* t)
7968 t = mono_reflection_type_get_underlying_system_type (t);
7976 * LOCKING: Assumes the loader lock is held.
7978 static MonoMethodSignature*
7979 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7980 MonoMethodSignature *sig;
7983 count = parameters? mono_array_length (parameters): 0;
7985 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7986 sig->param_count = count;
7987 sig->sentinelpos = -1; /* FIXME */
7988 for (i = 0; i < count; ++i) {
7989 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7990 sig->params [i] = mono_reflection_type_get_handle (pt);
7996 * LOCKING: Assumes the loader lock is held.
7998 static MonoMethodSignature*
7999 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
8000 MonoMethodSignature *sig;
8002 sig = parameters_to_signature (mp, ctor->parameters);
8003 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8004 sig->ret = &mono_defaults.void_class->byval_arg;
8009 * LOCKING: Assumes the loader lock is held.
8011 static MonoMethodSignature*
8012 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
8013 MonoMethodSignature *sig;
8015 sig = parameters_to_signature (mp, method->parameters);
8016 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8017 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8018 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8022 static MonoMethodSignature*
8023 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8024 MonoMethodSignature *sig;
8026 sig = parameters_to_signature (NULL, method->parameters);
8027 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8028 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8029 sig->generic_param_count = 0;
8034 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8036 MonoClass *klass = mono_object_class (prop);
8037 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8038 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8039 *name = mono_string_to_utf8 (pb->name);
8040 *type = pb->type->type;
8042 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8043 *name = g_strdup (p->property->name);
8044 if (p->property->get)
8045 *type = mono_method_signature (p->property->get)->ret;
8047 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8052 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8054 MonoClass *klass = mono_object_class (field);
8055 if (strcmp (klass->name, "FieldBuilder") == 0) {
8056 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8057 *name = mono_string_to_utf8 (fb->name);
8058 *type = fb->type->type;
8060 MonoReflectionField *f = (MonoReflectionField *)field;
8061 *name = g_strdup (f->field->name);
8062 *type = f->field->type;
8067 * Encode a value in a custom attribute stream of bytes.
8068 * The value to encode is either supplied as an object in argument val
8069 * (valuetypes are boxed), or as a pointer to the data in the
8071 * @type represents the type of the value
8072 * @buffer is the start of the buffer
8073 * @p the current position in the buffer
8074 * @buflen contains the size of the buffer and is used to return the new buffer size
8075 * if this needs to be realloced.
8076 * @retbuffer and @retp return the start and the position of the buffer
8079 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8081 MonoTypeEnum simple_type;
8083 if ((p-buffer) + 10 >= *buflen) {
8086 newbuf = g_realloc (buffer, *buflen);
8087 p = newbuf + (p-buffer);
8091 argval = ((char*)arg + sizeof (MonoObject));
8092 simple_type = type->type;
8094 switch (simple_type) {
8095 case MONO_TYPE_BOOLEAN:
8100 case MONO_TYPE_CHAR:
8103 swap_with_size (p, argval, 2, 1);
8109 swap_with_size (p, argval, 4, 1);
8113 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8123 swap_with_size (p, argval, 8, 1);
8129 swap_with_size (p, argval, 8, 1);
8132 case MONO_TYPE_VALUETYPE:
8133 if (type->data.klass->enumtype) {
8134 simple_type = type->data.klass->enum_basetype->type;
8137 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8140 case MONO_TYPE_STRING: {
8147 str = mono_string_to_utf8 ((MonoString*)arg);
8148 slen = strlen (str);
8149 if ((p-buffer) + 10 + slen >= *buflen) {
8153 newbuf = g_realloc (buffer, *buflen);
8154 p = newbuf + (p-buffer);
8157 mono_metadata_encode_value (slen, p, &p);
8158 memcpy (p, str, slen);
8163 case MONO_TYPE_CLASS: {
8171 k = mono_object_class (arg);
8172 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8173 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8174 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8177 if (rt && (rtc = mono_object_class (rt)) &&
8178 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8179 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8180 arg = (MonoObject *) rt;
8183 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8186 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8187 slen = strlen (str);
8188 if ((p-buffer) + 10 + slen >= *buflen) {
8192 newbuf = g_realloc (buffer, *buflen);
8193 p = newbuf + (p-buffer);
8196 mono_metadata_encode_value (slen, p, &p);
8197 memcpy (p, str, slen);
8202 case MONO_TYPE_SZARRAY: {
8204 MonoClass *eclass, *arg_eclass;
8207 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8210 len = mono_array_length ((MonoArray*)arg);
8212 *p++ = (len >> 8) & 0xff;
8213 *p++ = (len >> 16) & 0xff;
8214 *p++ = (len >> 24) & 0xff;
8216 *retbuffer = buffer;
8217 eclass = type->data.klass;
8218 arg_eclass = mono_object_class (arg)->element_class;
8221 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8222 eclass = mono_defaults.object_class;
8224 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8225 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8226 int elsize = mono_class_array_element_size (arg_eclass);
8227 for (i = 0; i < len; ++i) {
8228 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8231 } else if (eclass->valuetype && arg_eclass->valuetype) {
8232 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8233 int elsize = mono_class_array_element_size (eclass);
8234 for (i = 0; i < len; ++i) {
8235 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8239 for (i = 0; i < len; ++i) {
8240 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8245 case MONO_TYPE_OBJECT: {
8251 * The parameter type is 'object' but the type of the actual
8252 * argument is not. So we have to add type information to the blob
8253 * too. This is completely undocumented in the spec.
8257 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8262 klass = mono_object_class (arg);
8264 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8267 } else if (klass->enumtype) {
8269 } else if (klass == mono_defaults.string_class) {
8270 simple_type = MONO_TYPE_STRING;
8273 } else if (klass->rank == 1) {
8275 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8276 /* See Partition II, Appendix B3 */
8279 *p++ = klass->element_class->byval_arg.type;
8280 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8282 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8283 *p++ = simple_type = klass->byval_arg.type;
8286 g_error ("unhandled type in custom attr");
8288 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8289 slen = strlen (str);
8290 if ((p-buffer) + 10 + slen >= *buflen) {
8294 newbuf = g_realloc (buffer, *buflen);
8295 p = newbuf + (p-buffer);
8298 mono_metadata_encode_value (slen, p, &p);
8299 memcpy (p, str, slen);
8302 simple_type = klass->enum_basetype->type;
8306 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8309 *retbuffer = buffer;
8313 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8315 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8316 char *str = type_get_qualified_name (type, NULL);
8317 int slen = strlen (str);
8321 * This seems to be optional...
8324 mono_metadata_encode_value (slen, p, &p);
8325 memcpy (p, str, slen);
8328 } else if (type->type == MONO_TYPE_OBJECT) {
8330 } else if (type->type == MONO_TYPE_CLASS) {
8331 /* it should be a type: encode_cattr_value () has the check */
8334 mono_metadata_encode_value (type->type, p, &p);
8335 if (type->type == MONO_TYPE_SZARRAY)
8336 /* See the examples in Partition VI, Annex B */
8337 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8344 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8347 /* Preallocate a large enough buffer */
8348 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8349 char *str = type_get_qualified_name (type, NULL);
8352 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8353 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8359 len += strlen (name);
8361 if ((p-buffer) + 20 + len >= *buflen) {
8365 newbuf = g_realloc (buffer, *buflen);
8366 p = newbuf + (p-buffer);
8370 encode_field_or_prop_type (type, p, &p);
8372 len = strlen (name);
8373 mono_metadata_encode_value (len, p, &p);
8374 memcpy (p, name, len);
8376 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8378 *retbuffer = buffer;
8382 * mono_reflection_get_custom_attrs_blob:
8383 * @ctor: custom attribute constructor
8384 * @ctorArgs: arguments o the constructor
8390 * Creates the blob of data that needs to be saved in the metadata and that represents
8391 * the custom attributed described by @ctor, @ctorArgs etc.
8392 * Returns: a Byte array representing the blob of data.
8395 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8398 MonoMethodSignature *sig;
8403 MONO_ARCH_SAVE_REGS;
8405 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8406 /* sig is freed later so allocate it in the heap */
8407 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8409 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8412 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8414 p = buffer = g_malloc (buflen);
8415 /* write the prolog */
8418 for (i = 0; i < sig->param_count; ++i) {
8419 arg = mono_array_get (ctorArgs, MonoObject*, i);
8420 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8424 i += mono_array_length (properties);
8426 i += mono_array_length (fields);
8428 *p++ = (i >> 8) & 0xff;
8431 for (i = 0; i < mono_array_length (properties); ++i) {
8435 prop = mono_array_get (properties, gpointer, i);
8436 get_prop_name_and_type (prop, &pname, &ptype);
8437 *p++ = 0x54; /* PROPERTY signature */
8438 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8445 for (i = 0; i < mono_array_length (fields); ++i) {
8449 field = mono_array_get (fields, gpointer, i);
8450 get_field_name_and_type (field, &fname, &ftype);
8451 *p++ = 0x53; /* FIELD signature */
8452 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8457 g_assert (p - buffer <= buflen);
8458 buflen = p - buffer;
8459 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8460 p = mono_array_addr (result, char, 0);
8461 memcpy (p, buffer, buflen);
8463 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8469 static void* reflection_info_desc = NULL;
8470 #define MOVING_GC_REGISTER(addr) do { \
8471 if (!reflection_info_desc) { \
8473 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8475 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8478 #define MOVING_GC_REGISTER(addr)
8482 * mono_reflection_setup_internal_class:
8483 * @tb: a TypeBuilder object
8485 * Creates a MonoClass that represents the TypeBuilder.
8486 * This is a trick that lets us simplify a lot of reflection code
8487 * (and will allow us to support Build and Run assemblies easier).
8490 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8492 MonoClass *klass, *parent;
8494 MONO_ARCH_SAVE_REGS;
8496 mono_loader_lock ();
8499 /* check so we can compile corlib correctly */
8500 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8501 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8502 parent = tb->parent->type->data.klass;
8504 parent = my_mono_class_from_mono_type (tb->parent->type);
8510 /* the type has already being created: it means we just have to change the parent */
8511 if (tb->type.type) {
8512 klass = mono_class_from_mono_type (tb->type.type);
8513 klass->parent = NULL;
8514 /* fool mono_class_setup_parent */
8515 klass->supertypes = NULL;
8516 mono_class_setup_parent (klass, parent);
8517 mono_class_setup_mono_type (klass);
8518 mono_loader_unlock ();
8522 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8524 klass->image = &tb->module->dynamic_image->image;
8526 klass->inited = 1; /* we lie to the runtime */
8527 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8528 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8529 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8530 klass->flags = tb->attrs;
8532 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8534 klass->element_class = klass;
8536 MOVING_GC_REGISTER (&klass->reflection_info);
8537 klass->reflection_info = tb;
8539 /* Put into cache so mono_class_get () will find it */
8540 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8542 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8543 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8545 if (parent != NULL) {
8546 mono_class_setup_parent (klass, parent);
8547 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8548 const char *old_n = klass->name;
8549 /* trick to get relative numbering right when compiling corlib */
8550 klass->name = "BuildingObject";
8551 mono_class_setup_parent (klass, mono_defaults.object_class);
8552 klass->name = old_n;
8555 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8556 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8557 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8558 klass->instance_size = sizeof (MonoObject);
8559 klass->size_inited = 1;
8560 mono_class_setup_vtable_general (klass, NULL, 0);
8563 mono_class_setup_mono_type (klass);
8565 mono_class_setup_supertypes (klass);
8568 * FIXME: handle interfaces.
8571 tb->type.type = &klass->byval_arg;
8573 if (tb->nesting_type) {
8574 g_assert (tb->nesting_type->type);
8575 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8578 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8580 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8582 mono_loader_unlock ();
8586 * mono_reflection_setup_generic_class:
8587 * @tb: a TypeBuilder object
8589 * Setup the generic class before adding the first generic parameter.
8592 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8596 MONO_ARCH_SAVE_REGS;
8598 klass = my_mono_class_from_mono_type (tb->type.type);
8599 if (tb->generic_container)
8602 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8603 tb->generic_container->owner.klass = klass;
8607 * mono_reflection_create_generic_class:
8608 * @tb: a TypeBuilder object
8610 * Creates the generic class after all generic parameters have been added.
8613 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8618 MONO_ARCH_SAVE_REGS;
8620 klass = my_mono_class_from_mono_type (tb->type.type);
8622 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8624 if (klass->generic_container || (count == 0))
8627 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8629 klass->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
8631 klass->generic_container->owner.klass = klass;
8632 klass->generic_container->type_argc = count;
8633 klass->generic_container->type_params = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericParam) * count);
8635 for (i = 0; i < count; i++) {
8636 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8637 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8638 /*Make sure we are a diferent type instance */
8639 klass->generic_container->type_params [i].owner = klass->generic_container;
8640 klass->generic_container->type_params [i].pklass = NULL;
8642 g_assert (klass->generic_container->type_params [i].owner);
8645 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8649 * mono_reflection_create_internal_class:
8650 * @tb: a TypeBuilder object
8652 * Actually create the MonoClass that is associated with the TypeBuilder.
8655 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8659 MONO_ARCH_SAVE_REGS;
8661 klass = my_mono_class_from_mono_type (tb->type.type);
8663 mono_loader_lock ();
8664 if (klass->enumtype && klass->enum_basetype == NULL) {
8665 MonoReflectionFieldBuilder *fb;
8668 g_assert (tb->fields != NULL);
8669 g_assert (mono_array_length (tb->fields) >= 1);
8671 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8673 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8674 mono_loader_unlock ();
8678 klass->enum_basetype = fb->type->type;
8679 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8680 if (!klass->element_class)
8681 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8684 * get the element_class from the current corlib.
8686 ec = default_class_from_mono_type (klass->enum_basetype);
8687 klass->instance_size = ec->instance_size;
8688 klass->size_inited = 1;
8690 * this is almost safe to do with enums and it's needed to be able
8691 * to create objects of the enum type (for use in SetConstant).
8693 /* FIXME: Does this mean enums can't have method overrides ? */
8694 mono_class_setup_vtable_general (klass, NULL, 0);
8696 mono_loader_unlock ();
8699 static MonoMarshalSpec*
8700 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8701 MonoReflectionMarshal *minfo)
8703 MonoMarshalSpec *res;
8705 res = g_new0 (MonoMarshalSpec, 1);
8706 res->native = minfo->type;
8708 switch (minfo->type) {
8709 case MONO_NATIVE_LPARRAY:
8710 res->data.array_data.elem_type = minfo->eltype;
8711 if (minfo->has_size) {
8712 res->data.array_data.param_num = minfo->param_num;
8713 res->data.array_data.num_elem = minfo->count;
8714 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8717 res->data.array_data.param_num = -1;
8718 res->data.array_data.num_elem = -1;
8719 res->data.array_data.elem_mult = -1;
8723 case MONO_NATIVE_BYVALTSTR:
8724 case MONO_NATIVE_BYVALARRAY:
8725 res->data.array_data.num_elem = minfo->count;
8728 case MONO_NATIVE_CUSTOM:
8729 if (minfo->marshaltyperef)
8730 res->data.custom_data.custom_name =
8731 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8733 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8743 MonoReflectionMarshal*
8744 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8745 MonoMarshalSpec *spec)
8747 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8748 MonoReflectionMarshal *minfo;
8751 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8752 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8753 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8754 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8757 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8758 minfo->type = spec->native;
8760 switch (minfo->type) {
8761 case MONO_NATIVE_LPARRAY:
8762 minfo->eltype = spec->data.array_data.elem_type;
8763 minfo->count = spec->data.array_data.num_elem;
8764 minfo->param_num = spec->data.array_data.param_num;
8767 case MONO_NATIVE_BYVALTSTR:
8768 case MONO_NATIVE_BYVALARRAY:
8769 minfo->count = spec->data.array_data.num_elem;
8772 case MONO_NATIVE_CUSTOM:
8773 if (spec->data.custom_data.custom_name) {
8774 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8776 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8778 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8780 if (spec->data.custom_data.cookie)
8781 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8792 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8793 ReflectionMethodBuilder *rmb,
8794 MonoMethodSignature *sig)
8797 MonoMethodNormal *pm;
8798 MonoMarshalSpec **specs;
8799 MonoReflectionMethodAux *method_aux;
8805 * Methods created using a MethodBuilder should have their memory allocated
8806 * inside the image mempool, while dynamic methods should have their memory
8809 dynamic = rmb->refs != NULL;
8810 mp = dynamic ? NULL : klass->image->mempool;
8813 g_assert (!klass->generic_class);
8815 mono_loader_lock ();
8817 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8818 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8819 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8821 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8823 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8825 pm = (MonoMethodNormal*)m;
8827 m->dynamic = dynamic;
8829 m->flags = rmb->attrs;
8830 m->iflags = rmb->iattrs;
8831 m->name = mp_string_to_utf8 (mp, rmb->name);
8834 m->skip_visibility = rmb->skip_visibility;
8836 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8838 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8839 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8842 m->signature->pinvoke = 1;
8843 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8844 m->signature->pinvoke = 1;
8846 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8848 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8849 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8851 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8853 if (klass->image->dynamic)
8854 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8856 mono_loader_unlock ();
8859 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8860 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8861 MonoMethodHeader *header;
8863 gint32 max_stack, i;
8864 gint32 num_locals = 0;
8865 gint32 num_clauses = 0;
8869 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8870 code_size = rmb->ilgen->code_len;
8871 max_stack = rmb->ilgen->max_stack;
8872 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8873 if (rmb->ilgen->ex_handlers)
8874 num_clauses = method_count_clauses (rmb->ilgen);
8877 code = mono_array_addr (rmb->code, guint8, 0);
8878 code_size = mono_array_length (rmb->code);
8879 /* we probably need to run a verifier on the code... */
8889 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8890 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8891 header->code_size = code_size;
8892 header->code = mp_g_malloc (mp, code_size);
8893 memcpy ((char*)header->code, code, code_size);
8894 header->max_stack = max_stack;
8895 header->init_locals = rmb->init_locals;
8896 header->num_locals = num_locals;
8898 for (i = 0; i < num_locals; ++i) {
8899 MonoReflectionLocalBuilder *lb =
8900 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8902 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8903 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8906 header->num_clauses = num_clauses;
8908 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8909 rmb->ilgen, num_clauses);
8912 pm->header = header;
8915 if (rmb->generic_params) {
8916 int count = mono_array_length (rmb->generic_params);
8917 MonoGenericContainer *container;
8919 container = rmb->generic_container;
8921 m->is_generic = TRUE;
8922 mono_method_set_generic_container (m, container);
8924 container->type_argc = count;
8925 container->type_params = g_new0 (MonoGenericParam, count);
8926 container->owner.method = m;
8928 for (i = 0; i < count; i++) {
8929 MonoReflectionGenericParam *gp =
8930 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8932 container->type_params [i] = *gp->type.type->data.generic_param;
8935 if (klass->generic_container) {
8936 container->parent = klass->generic_container;
8937 container->context.class_inst = klass->generic_container->context.class_inst;
8939 container->context.method_inst = mono_get_shared_generic_inst (container);
8943 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8947 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8949 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8950 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8951 for (i = 0; i < rmb->nrefs; ++i)
8952 data [i + 1] = rmb->refs [i];
8957 /* Parameter info */
8960 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8961 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8962 for (i = 0; i <= m->signature->param_count; ++i) {
8963 MonoReflectionParamBuilder *pb;
8964 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8965 if ((i > 0) && (pb->attrs)) {
8966 /* Make a copy since it might point to a shared type structure */
8967 /* FIXME: Alloc this from a mempool */
8968 m->signature->params [i - 1] = mono_metadata_type_dup (NULL, m->signature->params [i - 1]);
8969 m->signature->params [i - 1]->attrs = pb->attrs;
8972 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8973 MonoDynamicImage *assembly;
8974 guint32 idx, def_type, len;
8978 if (!method_aux->param_defaults) {
8979 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8980 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8982 assembly = (MonoDynamicImage*)klass->image;
8983 idx = encode_constant (assembly, pb->def_value, &def_type);
8984 /* Copy the data from the blob since it might get realloc-ed */
8985 p = assembly->blob.data + idx;
8986 len = mono_metadata_decode_blob_size (p, &p2);
8988 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8989 method_aux->param_default_types [i] = def_type;
8990 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8994 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
8996 if (!method_aux->param_cattr)
8997 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8998 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
9004 /* Parameter marshalling */
9007 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9008 MonoReflectionParamBuilder *pb;
9009 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9010 if (pb->marshal_info) {
9012 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
9013 specs [pb->position] =
9014 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
9018 if (specs != NULL) {
9020 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9021 method_aux->param_marshall = specs;
9024 if (klass->image->dynamic && method_aux)
9025 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9027 mono_loader_unlock ();
9033 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9035 ReflectionMethodBuilder rmb;
9036 MonoMethodSignature *sig;
9038 mono_loader_lock ();
9039 sig = ctor_builder_to_signature (klass->image->mempool, mb);
9040 mono_loader_unlock ();
9042 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9044 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9045 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9047 /* If we are in a generic class, we might be called multiple times from inflate_method */
9048 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9049 /* ilgen is no longer needed */
9057 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9059 ReflectionMethodBuilder rmb;
9060 MonoMethodSignature *sig;
9062 mono_loader_lock ();
9063 sig = method_builder_to_signature (klass->image->mempool, mb);
9064 mono_loader_unlock ();
9066 reflection_methodbuilder_from_method_builder (&rmb, mb);
9068 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9069 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9071 /* If we are in a generic class, we might be called multiple times from inflate_method */
9072 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9073 /* ilgen is no longer needed */
9079 static MonoClassField*
9080 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9082 MonoClassField *field;
9086 field = g_new0 (MonoClassField, 1);
9088 field->name = mono_string_to_utf8 (fb->name);
9090 /* FIXME: handle type modifiers */
9091 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9092 field->type->attrs = fb->attrs;
9094 field->type = fb->type->type;
9096 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9097 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
9098 if (fb->offset != -1)
9099 field->offset = fb->offset;
9100 field->parent = klass;
9101 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9103 if (fb->def_value) {
9104 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9105 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9106 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9107 /* Copy the data from the blob since it might get realloc-ed */
9108 p = assembly->blob.data + idx;
9109 len = mono_metadata_decode_blob_size (p, &p2);
9111 field->data = g_malloc (len);
9112 memcpy ((gpointer)field->data, p, len);
9119 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9122 MonoReflectionTypeBuilder *tb = NULL;
9123 gboolean is_dynamic = FALSE;
9127 mono_loader_lock ();
9129 domain = mono_object_domain (type);
9131 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9132 tb = (MonoReflectionTypeBuilder *) type;
9135 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9136 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9138 tb = rgi->generic_type;
9142 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9143 if (tb && tb->generic_container)
9144 mono_reflection_create_generic_class (tb);
9146 klass = mono_class_from_mono_type (type->type);
9147 if (!klass->generic_container) {
9148 mono_loader_unlock ();
9152 if (klass->wastypebuilder) {
9153 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9158 mono_loader_unlock ();
9160 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9162 return &geninst->byval_arg;
9166 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9168 MonoGenericClass *gclass;
9169 MonoGenericInst *inst;
9171 g_assert (klass->generic_container);
9173 inst = mono_metadata_get_generic_inst (type_argc, types);
9174 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9176 return mono_generic_class_get_class (gclass);
9179 MonoReflectionMethod*
9180 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9183 MonoMethod *method, *inflated;
9184 MonoMethodInflated *imethod;
9185 MonoReflectionMethodBuilder *mb = NULL;
9186 MonoGenericContext tmp_context;
9187 MonoGenericInst *ginst;
9188 MonoType **type_argv;
9191 MONO_ARCH_SAVE_REGS;
9192 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9193 MonoReflectionTypeBuilder *tb;
9196 mb = (MonoReflectionMethodBuilder *) rmethod;
9197 tb = (MonoReflectionTypeBuilder *) mb->type;
9198 klass = mono_class_from_mono_type (tb->type.type);
9200 method = methodbuilder_to_mono_method (klass, mb);
9202 method = rmethod->method;
9205 klass = method->klass;
9207 if (method->is_inflated)
9208 method = ((MonoMethodInflated *) method)->declaring;
9210 count = mono_method_signature (method)->generic_param_count;
9211 if (count != mono_array_length (types))
9214 type_argv = g_new0 (MonoType *, count);
9215 for (i = 0; i < count; i++) {
9216 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9217 type_argv [i] = garg->type;
9219 ginst = mono_metadata_get_generic_inst (count, type_argv);
9222 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9223 tmp_context.method_inst = ginst;
9225 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9226 imethod = (MonoMethodInflated *) inflated;
9228 if (method->klass->image->dynamic) {
9229 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9231 * This table maps metadata structures representing inflated methods/fields
9232 * to the reflection objects representing their generic definitions.
9234 mono_loader_lock ();
9235 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9236 mono_loader_unlock ();
9239 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9243 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9245 MonoMethodInflated *imethod;
9246 MonoGenericContext *context;
9249 g_assert (klass->generic_class);
9250 context = mono_class_get_context (klass);
9252 if (klass->method.count) {
9253 /* Find the already created inflated method */
9254 for (i = 0; i < klass->method.count; ++i) {
9255 g_assert (klass->methods [i]->is_inflated);
9256 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9259 g_assert (i < klass->method.count);
9260 imethod = (MonoMethodInflated*)klass->methods [i];
9262 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9265 if (method->is_generic && method->klass->image->dynamic) {
9266 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9268 mono_loader_lock ();
9269 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9270 mono_loader_unlock ();
9272 return (MonoMethod *) imethod;
9276 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9281 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9283 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9284 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9285 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9287 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9288 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9289 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9290 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9291 method = ((MonoReflectionMethod *) obj)->method;
9293 method = NULL; /* prevent compiler warning */
9294 g_assert_not_reached ();
9297 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9301 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9302 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9305 MonoGenericClass *gclass;
9306 MonoDynamicGenericClass *dgclass;
9307 MonoClass *klass, *gklass;
9310 MONO_ARCH_SAVE_REGS;
9312 klass = mono_class_from_mono_type (type->type.type);
9313 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9314 gclass = type->type.type->data.generic_class;
9316 g_assert (gclass->is_dynamic);
9317 dgclass = (MonoDynamicGenericClass *) gclass;
9319 if (dgclass->initialized)
9322 gklass = gclass->container_class;
9323 mono_class_init (gklass);
9325 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9326 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9327 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9328 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9329 dgclass->count_events = events ? mono_array_length (events) : 0;
9331 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9332 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9333 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9334 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9335 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9337 for (i = 0; i < dgclass->count_methods; i++) {
9338 MonoObject *obj = mono_array_get (methods, gpointer, i);
9340 dgclass->methods [i] = inflate_method (type, obj);
9343 for (i = 0; i < dgclass->count_ctors; i++) {
9344 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9346 dgclass->ctors [i] = inflate_method (type, obj);
9349 for (i = 0; i < dgclass->count_fields; i++) {
9350 MonoObject *obj = mono_array_get (fields, gpointer, i);
9351 MonoClassField *field;
9352 MonoInflatedField *ifield;
9354 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9355 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9356 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9357 field = ((MonoReflectionField *) obj)->field;
9359 field = NULL; /* prevent compiler warning */
9360 g_assert_not_reached ();
9363 ifield = g_new0 (MonoInflatedField, 1);
9364 ifield->generic_type = field->type;
9365 MOVING_GC_REGISTER (&ifield->reflection_info);
9366 ifield->reflection_info = obj;
9368 dgclass->fields [i] = *field;
9369 dgclass->fields [i].parent = klass;
9370 dgclass->fields [i].generic_info = ifield;
9371 dgclass->fields [i].type = mono_class_inflate_generic_type (
9372 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9375 for (i = 0; i < dgclass->count_properties; i++) {
9376 MonoObject *obj = mono_array_get (properties, gpointer, i);
9377 MonoProperty *property = &dgclass->properties [i];
9379 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9380 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9382 property->parent = klass;
9383 property->attrs = pb->attrs;
9384 property->name = mono_string_to_utf8 (pb->name);
9386 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9388 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9389 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9390 *property = *((MonoReflectionProperty *) obj)->property;
9393 property->get = inflate_mono_method (klass, property->get, NULL);
9395 property->set = inflate_mono_method (klass, property->set, NULL);
9397 g_assert_not_reached ();
9400 for (i = 0; i < dgclass->count_events; i++) {
9401 MonoObject *obj = mono_array_get (events, gpointer, i);
9402 MonoEvent *event = &dgclass->events [i];
9404 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9405 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9407 event->parent = klass;
9408 event->attrs = eb->attrs;
9409 event->name = mono_string_to_utf8 (eb->name);
9411 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9412 if (eb->remove_method)
9413 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9414 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9415 *event = *((MonoReflectionEvent *) obj)->event;
9418 event->add = inflate_mono_method (klass, event->add, NULL);
9420 event->remove = inflate_mono_method (klass, event->remove, NULL);
9422 g_assert_not_reached ();
9425 dgclass->initialized = TRUE;
9429 ensure_runtime_vtable (MonoClass *klass)
9431 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9434 if (!tb || klass->wastypebuilder)
9437 ensure_runtime_vtable (klass->parent);
9439 num = tb->ctors? mono_array_length (tb->ctors): 0;
9440 num += tb->num_methods;
9441 klass->method.count = num;
9442 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9443 num = tb->ctors? mono_array_length (tb->ctors): 0;
9444 for (i = 0; i < num; ++i)
9445 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9446 num = tb->num_methods;
9448 for (i = 0; i < num; ++i)
9449 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9451 if (tb->interfaces) {
9452 klass->interface_count = mono_array_length (tb->interfaces);
9453 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9454 for (i = 0; i < klass->interface_count; ++i) {
9455 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9456 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9460 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9461 for (i = 0; i < klass->method.count; ++i)
9462 klass->methods [i]->slot = i;
9464 mono_class_setup_interface_offsets (klass);
9468 * The generic vtable is needed even if image->run is not set since some
9469 * runtime code like ves_icall_Type_GetMethodsByName depends on
9470 * method->slot being defined.
9474 * tb->methods could not be freed since it is used for determining
9475 * overrides during dynamic vtable construction.
9480 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9482 MonoReflectionTypeBuilder *tb;
9488 g_assert (klass->image->dynamic);
9490 if (!klass->reflection_info)
9493 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9495 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9499 for (i = 0; i < tb->num_methods; ++i) {
9500 MonoReflectionMethodBuilder *mb =
9501 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9502 if (mb->override_method)
9508 *overrides = g_new0 (MonoMethod*, onum * 2);
9511 for (i = 0; i < tb->num_methods; ++i) {
9512 MonoReflectionMethodBuilder *mb =
9513 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9514 if (mb->override_method) {
9515 (*overrides) [onum * 2] =
9516 mb->override_method->method;
9517 (*overrides) [onum * 2 + 1] =
9520 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9521 g_assert (mb->override_method->method);
9522 g_assert (mb->mhandle);
9529 *num_overrides = onum;
9533 typebuilder_setup_fields (MonoClass *klass)
9535 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9536 MonoReflectionFieldBuilder *fb;
9537 MonoClassField *field;
9542 klass->field.count = tb->num_fields;
9543 klass->field.first = 0;
9545 if (!klass->field.count)
9548 klass->fields = g_new0 (MonoClassField, klass->field.count);
9550 for (i = 0; i < klass->field.count; ++i) {
9551 fb = mono_array_get (tb->fields, gpointer, i);
9552 field = &klass->fields [i];
9553 field->name = mono_string_to_utf8 (fb->name);
9555 /* FIXME: handle type modifiers */
9556 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9557 field->type->attrs = fb->attrs;
9559 field->type = fb->type->type;
9561 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9562 field->data = mono_array_addr (fb->rva_data, char, 0);
9563 if (fb->offset != -1)
9564 field->offset = fb->offset;
9565 field->parent = klass;
9567 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9569 if (fb->def_value) {
9570 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9571 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9572 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9573 /* Copy the data from the blob since it might get realloc-ed */
9574 p = assembly->blob.data + idx;
9575 len = mono_metadata_decode_blob_size (p, &p2);
9577 field->data = g_malloc (len);
9578 memcpy ((gpointer)field->data, p, len);
9581 mono_class_layout_fields (klass);
9585 typebuilder_setup_properties (MonoClass *klass)
9587 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9588 MonoReflectionPropertyBuilder *pb;
9591 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9592 klass->property.first = 0;
9594 klass->properties = g_new0 (MonoProperty, klass->property.count);
9595 for (i = 0; i < klass->property.count; ++i) {
9596 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9597 klass->properties [i].parent = klass;
9598 klass->properties [i].attrs = pb->attrs;
9599 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9601 klass->properties [i].get = pb->get_method->mhandle;
9603 klass->properties [i].set = pb->set_method->mhandle;
9605 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9609 MonoReflectionEvent *
9610 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9612 MonoEvent *event = g_new0 (MonoEvent, 1);
9616 klass = my_mono_class_from_mono_type (tb->type.type);
9618 event->parent = klass;
9619 event->attrs = eb->attrs;
9620 event->name = mono_string_to_utf8 (eb->name);
9622 event->add = eb->add_method->mhandle;
9623 if (eb->remove_method)
9624 event->remove = eb->remove_method->mhandle;
9625 if (eb->raise_method)
9626 event->raise = eb->raise_method->mhandle;
9628 if (eb->other_methods) {
9629 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9630 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9631 MonoReflectionMethodBuilder *mb =
9632 mono_array_get (eb->other_methods,
9633 MonoReflectionMethodBuilder*, j);
9634 event->other [j] = mb->mhandle;
9638 return mono_event_get_object (mono_object_domain (tb), klass, event);
9642 typebuilder_setup_events (MonoClass *klass)
9644 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9645 MonoReflectionEventBuilder *eb;
9648 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9649 klass->event.first = 0;
9651 klass->events = g_new0 (MonoEvent, klass->event.count);
9652 for (i = 0; i < klass->event.count; ++i) {
9653 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9654 klass->events [i].parent = klass;
9655 klass->events [i].attrs = eb->attrs;
9656 klass->events [i].name = mono_string_to_utf8 (eb->name);
9658 klass->events [i].add = eb->add_method->mhandle;
9659 if (eb->remove_method)
9660 klass->events [i].remove = eb->remove_method->mhandle;
9661 if (eb->raise_method)
9662 klass->events [i].raise = eb->raise_method->mhandle;
9664 if (eb->other_methods) {
9665 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9666 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9667 MonoReflectionMethodBuilder *mb =
9668 mono_array_get (eb->other_methods,
9669 MonoReflectionMethodBuilder*, j);
9670 klass->events [i].other [j] = mb->mhandle;
9677 remove_instantiations_of (gpointer key,
9681 MonoType *type = (MonoType*)key;
9682 MonoClass *klass = (MonoClass*)user_data;
9684 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
9691 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9695 MonoReflectionType* res;
9698 MONO_ARCH_SAVE_REGS;
9700 domain = mono_object_domain (tb);
9701 klass = my_mono_class_from_mono_type (tb->type.type);
9703 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9706 * we need to lock the domain because the lock will be taken inside
9707 * So, we need to keep the locking order correct.
9709 mono_domain_lock (domain);
9710 mono_loader_lock ();
9711 if (klass->wastypebuilder) {
9712 mono_loader_unlock ();
9713 mono_domain_unlock (domain);
9714 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9717 * Fields to set in klass:
9718 * the various flags: delegate/unicode/contextbound etc.
9720 klass->flags = tb->attrs;
9721 klass->has_cctor = 1;
9722 klass->has_finalize = 1;
9725 if (!((MonoDynamicImage*)klass->image)->run) {
9726 if (klass->generic_container) {
9727 /* FIXME: The code below can't handle generic classes */
9728 klass->wastypebuilder = TRUE;
9729 mono_loader_unlock ();
9730 mono_domain_unlock (domain);
9731 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9736 /* enums are done right away */
9737 if (!klass->enumtype)
9738 ensure_runtime_vtable (klass);
9741 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9742 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9743 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9747 /* fields and object layout */
9748 if (klass->parent) {
9749 if (!klass->parent->size_inited)
9750 mono_class_init (klass->parent);
9751 klass->instance_size = klass->parent->instance_size;
9752 klass->sizes.class_size = 0;
9753 klass->min_align = klass->parent->min_align;
9754 /* if the type has no fields we won't call the field_setup
9755 * routine which sets up klass->has_references.
9757 klass->has_references |= klass->parent->has_references;
9759 klass->instance_size = sizeof (MonoObject);
9760 klass->min_align = 1;
9763 /* FIXME: handle packing_size and instance_size */
9764 typebuilder_setup_fields (klass);
9766 typebuilder_setup_properties (klass);
9768 typebuilder_setup_events (klass);
9770 klass->wastypebuilder = TRUE;
9773 * If we are a generic TypeBuilder, there might be instantiations in the type cache
9774 * which have type System.Reflection.MonoGenericClass, but after the type is created,
9775 * we want to return normal System.MonoType objects, so clear these out from the cache.
9777 if (domain->type_hash && klass->generic_container)
9778 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
9780 mono_loader_unlock ();
9781 mono_domain_unlock (domain);
9783 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
9784 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
9785 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
9788 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9789 g_assert (res != (MonoReflectionType*)tb);
9795 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9797 MonoGenericParam *param;
9800 MONO_ARCH_SAVE_REGS;
9802 param = g_new0 (MonoGenericParam, 1);
9804 if (gparam->mbuilder) {
9805 if (!gparam->mbuilder->generic_container) {
9806 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9807 gparam->mbuilder->generic_container->is_method = TRUE;
9809 param->owner = gparam->mbuilder->generic_container;
9810 } else if (gparam->tbuilder) {
9811 g_assert (gparam->tbuilder->generic_container);
9812 param->owner = gparam->tbuilder->generic_container;
9815 param->name = mono_string_to_utf8 (gparam->name);
9816 param->num = gparam->index;
9818 image = &gparam->tbuilder->module->dynamic_image->image;
9819 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9821 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
9822 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9824 gparam->type.type = g_new0 (MonoType, 1);
9825 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9826 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9827 gparam->type.type->data.generic_param = param;
9831 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9833 MonoDynamicImage *assembly = sig->module->dynamic_image;
9834 guint32 na = mono_array_length (sig->arguments);
9839 sigbuffer_init (&buf, 32);
9841 sigbuffer_add_value (&buf, 0x07);
9842 sigbuffer_add_value (&buf, na);
9843 for (i = 0; i < na; ++i) {
9844 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9845 encode_reflection_type (assembly, type, &buf);
9848 buflen = buf.p - buf.buf;
9849 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9850 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9851 sigbuffer_free (&buf);
9857 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9859 MonoDynamicImage *assembly = sig->module->dynamic_image;
9860 guint32 na = mono_array_length (sig->arguments);
9865 sigbuffer_init (&buf, 32);
9867 sigbuffer_add_value (&buf, 0x06);
9868 for (i = 0; i < na; ++i) {
9869 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9870 encode_reflection_type (assembly, type, &buf);
9873 buflen = buf.p - buf.buf;
9874 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9875 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9876 sigbuffer_free (&buf);
9882 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9884 ReflectionMethodBuilder rmb;
9885 MonoMethodSignature *sig;
9890 sig = dynamic_method_to_signature (mb);
9892 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9895 * Resolve references.
9898 * Every second entry in the refs array is reserved for storing handle_class,
9899 * which is needed by the ldtoken implementation in the JIT.
9901 rmb.nrefs = mb->nrefs;
9902 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9903 for (i = 0; i < mb->nrefs; i += 2) {
9904 MonoClass *handle_class;
9906 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
9908 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9909 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9911 * The referenced DynamicMethod should already be created by the managed
9912 * code, except in the case of circular references. In that case, we store
9913 * method in the refs array, and fix it up later when the referenced
9914 * DynamicMethod is created.
9916 if (method->mhandle) {
9917 ref = method->mhandle;
9919 /* FIXME: GC object stored in unmanaged memory */
9922 /* FIXME: GC object stored in unmanaged memory */
9923 method->referenced_by = g_slist_append (method->referenced_by, mb);
9925 handle_class = mono_defaults.methodhandle_class;
9927 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
9930 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9935 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9936 rmb.refs [i + 1] = handle_class;
9939 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
9941 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9943 /* Fix up refs entries pointing at us */
9944 for (l = mb->referenced_by; l; l = l->next) {
9945 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
9946 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
9949 g_assert (method->mhandle);
9951 data = (gpointer*)wrapper->method_data;
9952 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
9953 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
9954 data [i + 1] = mb->mhandle;
9957 g_slist_free (mb->referenced_by);
9961 /* ilgen is no longer needed */
9966 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
9971 mono_runtime_free_method (
9972 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
9977 * mono_reflection_is_valid_dynamic_token:
9979 * Returns TRUE if token is valid.
9983 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
9985 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
9989 * mono_reflection_lookup_dynamic_token:
9991 * Finish the Builder object pointed to by TOKEN and return the corresponding
9992 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
9993 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
9997 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
9999 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10003 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10006 g_assert_not_reached ();
10012 handle_class = &klass;
10013 return resolve_object (image, obj, handle_class, context);
10017 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10019 gpointer result = NULL;
10021 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10022 result = mono_string_intern ((MonoString*)obj);
10023 *handle_class = NULL;
10025 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10026 MonoReflectionType *tb = (MonoReflectionType*)obj;
10028 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10029 result = mono_class_from_mono_type (inflated);
10030 mono_metadata_free_type (inflated);
10032 result = mono_class_from_mono_type (tb->type);
10034 *handle_class = mono_defaults.typehandle_class;
10036 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10037 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10038 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10039 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10040 result = ((MonoReflectionMethod*)obj)->method;
10042 result = mono_class_inflate_generic_method (result, context);
10043 *handle_class = mono_defaults.methodhandle_class;
10045 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10046 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10047 result = mb->mhandle;
10049 /* Type is not yet created */
10050 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10052 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10055 * Hopefully this has been filled in by calling CreateType() on the
10059 * TODO: This won't work if the application finishes another
10060 * TypeBuilder instance instead of this one.
10062 result = mb->mhandle;
10065 result = mono_class_inflate_generic_method (result, context);
10066 *handle_class = mono_defaults.methodhandle_class;
10067 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10068 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10070 result = cb->mhandle;
10072 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10074 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10075 result = cb->mhandle;
10078 result = mono_class_inflate_generic_method (result, context);
10079 *handle_class = mono_defaults.methodhandle_class;
10080 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10081 result = ((MonoReflectionField*)obj)->field;
10082 *handle_class = mono_defaults.fieldhandle_class;
10084 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10085 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10086 result = fb->handle;
10089 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10091 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10092 result = fb->handle;
10095 if (fb->handle && fb->handle->parent->generic_container) {
10096 MonoClass *klass = fb->handle->parent;
10097 MonoClass *inflated = mono_class_from_mono_type (mono_class_inflate_generic_type (&klass->byval_arg, context));
10099 result = mono_class_get_field_from_name (inflated, fb->handle->name);
10102 *handle_class = mono_defaults.fieldhandle_class;
10103 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10104 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10107 klass = tb->type.type->data.klass;
10108 if (klass->wastypebuilder) {
10109 /* Already created */
10113 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10114 result = tb->type.type->data.klass;
10117 *handle_class = mono_defaults.typehandle_class;
10118 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10119 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10120 MonoMethodSignature *sig;
10123 if (helper->arguments)
10124 nargs = mono_array_length (helper->arguments);
10128 sig = mono_metadata_signature_alloc (image, nargs);
10129 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10130 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10132 if (helper->call_conv == 0) /* unmanaged */
10133 sig->call_convention = helper->unmanaged_call_conv - 1;
10135 if (helper->call_conv & 0x02)
10136 sig->call_convention = MONO_CALL_VARARG;
10138 sig->call_convention = MONO_CALL_DEFAULT;
10140 sig->param_count = nargs;
10141 /* TODO: Copy type ? */
10142 sig->ret = helper->return_type->type;
10143 for (i = 0; i < nargs; ++i) {
10144 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10145 sig->params [i] = rt->type;
10149 *handle_class = NULL;
10150 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10151 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10152 /* Already created by the managed code */
10153 g_assert (method->mhandle);
10154 result = method->mhandle;
10155 *handle_class = mono_defaults.methodhandle_class;
10156 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10157 MonoReflectionType *tb = (MonoReflectionType*)obj;
10158 result = mono_class_from_mono_type (mono_class_inflate_generic_type (tb->type, context));
10159 *handle_class = mono_defaults.typehandle_class;
10161 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10162 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10163 result = mono_class_from_mono_type (mono_class_inflate_generic_type (ref->type.type, context));
10164 *handle_class = mono_defaults.typehandle_class;
10166 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10167 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10168 MonoClass *inflated = mono_class_from_mono_type (f->inst->type.type);
10170 g_assert (f->fb->handle);
10171 result = mono_class_get_field_from_name (inflated, f->fb->handle->name);
10173 *handle_class = mono_defaults.fieldhandle_class;
10174 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10175 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10176 MonoClass *inflated_klass = mono_class_from_mono_type (mono_class_inflate_generic_type (c->inst->type.type, context));
10177 g_assert (c->cb->mhandle);
10178 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10179 *handle_class = mono_defaults.methodhandle_class;
10180 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10181 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10182 MonoClass *inflated_klass = mono_class_from_mono_type (mono_class_inflate_generic_type (m->inst->type.type, context));
10183 g_assert (m->mb->mhandle);
10184 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10185 *handle_class = mono_defaults.methodhandle_class;
10187 g_print (obj->vtable->klass->name);
10188 g_assert_not_reached ();
10194 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10195 const static guint32 declsec_flags_map[] = {
10196 0x00000000, /* empty */
10197 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10198 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10199 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10200 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10201 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10202 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10203 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10204 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10205 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10206 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10207 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10208 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10209 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10210 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10211 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10212 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10213 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10214 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10218 * Returns flags that includes all available security action associated to the handle.
10219 * @token: metadata token (either for a class or a method)
10220 * @image: image where resides the metadata.
10223 mono_declsec_get_flags (MonoImage *image, guint32 token)
10225 int index = mono_metadata_declsec_from_index (image, token);
10226 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10227 guint32 result = 0;
10231 /* HasSecurity can be present for other, not specially encoded, attributes,
10232 e.g. SuppressUnmanagedCodeSecurityAttribute */
10236 for (i = index; i < t->rows; i++) {
10237 guint32 cols [MONO_DECL_SECURITY_SIZE];
10239 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10240 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10243 action = cols [MONO_DECL_SECURITY_ACTION];
10244 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10245 result |= declsec_flags_map [action];
10247 g_assert_not_reached ();
10254 * Get the security actions (in the form of flags) associated with the specified method.
10256 * @method: The method for which we want the declarative security flags.
10257 * Return the declarative security flags for the method (only).
10259 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10260 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10263 mono_declsec_flags_from_method (MonoMethod *method)
10265 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10266 /* FIXME: No cache (for the moment) */
10267 guint32 idx = mono_method_get_index (method);
10268 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10269 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10270 return mono_declsec_get_flags (method->klass->image, idx);
10276 * Get the security actions (in the form of flags) associated with the specified class.
10278 * @klass: The class for which we want the declarative security flags.
10279 * Return the declarative security flags for the class.
10281 * Note: We cache the flags inside the MonoClass structure as this will get
10282 * called very often (at least for each method).
10285 mono_declsec_flags_from_class (MonoClass *klass)
10287 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10288 if (!klass->declsec_flags) {
10289 guint32 idx = mono_metadata_token_index (klass->type_token);
10290 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10291 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10292 /* we cache the flags on classes */
10293 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10295 return klass->declsec_flags;
10301 * Get the security actions (in the form of flags) associated with the specified assembly.
10303 * @assembly: The assembly for which we want the declarative security flags.
10304 * Return the declarative security flags for the assembly.
10307 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10309 guint32 idx = 1; /* there is only one assembly */
10310 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10311 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10312 return mono_declsec_get_flags (assembly->image, idx);
10317 * Fill actions for the specific index (which may either be an encoded class token or
10318 * an encoded method token) from the metadata image.
10319 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10322 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10323 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10325 MonoBoolean result = FALSE;
10327 guint32 cols [MONO_DECL_SECURITY_SIZE];
10328 int index = mono_metadata_declsec_from_index (image, token);
10331 t = &image->tables [MONO_TABLE_DECLSECURITY];
10332 for (i = index; i < t->rows; i++) {
10333 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10335 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10338 /* if present only replace (class) permissions with method permissions */
10339 /* if empty accept either class or method permissions */
10340 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10341 if (!actions->demand.blob) {
10342 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10343 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10344 actions->demand.blob = (char*) (blob + 2);
10345 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10348 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10349 if (!actions->noncasdemand.blob) {
10350 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10351 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10352 actions->noncasdemand.blob = (char*) (blob + 2);
10353 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10356 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10357 if (!actions->demandchoice.blob) {
10358 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10359 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10360 actions->demandchoice.blob = (char*) (blob + 2);
10361 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10371 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
10372 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10374 guint32 idx = mono_metadata_token_index (klass->type_token);
10375 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10376 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10377 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
10381 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
10382 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10384 guint32 idx = mono_method_get_index (method);
10385 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10386 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10387 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10391 * Collect all actions (that requires to generate code in mini) assigned for
10392 * the specified method.
10393 * Note: Don't use the content of actions if the function return FALSE.
10396 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10398 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
10399 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10400 MonoBoolean result = FALSE;
10403 /* quick exit if no declarative security is present in the metadata */
10404 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10407 /* we want the original as the wrapper is "free" of the security informations */
10408 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10409 method = mono_marshal_method_from_wrapper (method);
10414 /* First we look for method-level attributes */
10415 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10416 mono_class_init (method->klass);
10417 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10419 result = mono_declsec_get_method_demands_params (method, demands,
10420 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10423 /* Here we use (or create) the class declarative cache to look for demands */
10424 flags = mono_declsec_flags_from_class (method->klass);
10425 if (flags & mask) {
10427 mono_class_init (method->klass);
10428 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10430 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10431 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10434 /* The boolean return value is used as a shortcut in case nothing needs to
10435 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10441 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10443 * Note: Don't use the content of actions if the function return FALSE.
10446 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10448 MonoBoolean result = FALSE;
10451 /* quick exit if no declarative security is present in the metadata */
10452 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10455 /* we want the original as the wrapper is "free" of the security informations */
10456 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10457 method = mono_marshal_method_from_wrapper (method);
10462 /* results are independant - zeroize both */
10463 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10464 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10466 /* First we look for method-level attributes */
10467 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10468 mono_class_init (method->klass);
10470 result = mono_declsec_get_method_demands_params (method, cmethod,
10471 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10474 /* Here we use (or create) the class declarative cache to look for demands */
10475 flags = mono_declsec_flags_from_class (method->klass);
10476 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10477 mono_class_init (method->klass);
10479 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10480 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10487 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10489 * @klass The inherited class - this is the class that provides the security check (attributes)
10491 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10493 * Note: Don't use the content of actions if the function return FALSE.
10496 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10498 MonoBoolean result = FALSE;
10501 /* quick exit if no declarative security is present in the metadata */
10502 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10505 /* Here we use (or create) the class declarative cache to look for demands */
10506 flags = mono_declsec_flags_from_class (klass);
10507 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10508 mono_class_init (klass);
10509 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10511 result |= mono_declsec_get_class_demands_params (klass, demands,
10512 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10519 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10521 * Note: Don't use the content of actions if the function return FALSE.
10524 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10526 /* quick exit if no declarative security is present in the metadata */
10527 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10530 /* we want the original as the wrapper is "free" of the security informations */
10531 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10532 method = mono_marshal_method_from_wrapper (method);
10537 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10538 mono_class_init (method->klass);
10539 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10541 return mono_declsec_get_method_demands_params (method, demands,
10542 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10549 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10551 guint32 cols [MONO_DECL_SECURITY_SIZE];
10555 int index = mono_metadata_declsec_from_index (image, token);
10559 t = &image->tables [MONO_TABLE_DECLSECURITY];
10560 for (i = index; i < t->rows; i++) {
10561 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10563 /* shortcut - index are ordered */
10564 if (token != cols [MONO_DECL_SECURITY_PARENT])
10567 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10568 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10569 entry->blob = (char*) (metadata + 2);
10570 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10579 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10581 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10582 guint32 idx = mono_method_get_index (method);
10583 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10584 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10585 return get_declsec_action (method->klass->image, idx, action, entry);
10591 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10594 guint32 flags = mono_declsec_flags_from_class (klass);
10595 if (declsec_flags_map [action] & flags) {
10596 guint32 idx = mono_metadata_token_index (klass->type_token);
10597 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10598 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10599 return get_declsec_action (klass->image, idx, action, entry);
10605 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10607 guint32 idx = 1; /* there is only one assembly */
10608 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10609 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10611 return get_declsec_action (assembly->image, idx, action, entry);
10615 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10617 MonoObject *res, *exc;
10619 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10620 static MonoMethod *method = NULL;
10622 if (!System_Reflection_Emit_TypeBuilder) {
10623 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10624 g_assert (System_Reflection_Emit_TypeBuilder);
10626 if (method == NULL) {
10627 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10632 * The result of mono_type_get_object () might be a System.MonoType but we
10633 * need a TypeBuilder so use klass->reflection_info.
10635 g_assert (klass->reflection_info);
10636 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10638 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10640 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10644 return *(MonoBoolean*)mono_object_unbox (res);