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);
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);
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)
1586 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1588 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1591 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1595 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1600 if (!assembly->save)
1603 sigbuffer_init (&buf, 32);
1605 sigbuffer_add_value (&buf, 0x06);
1606 /* encode custom attributes before the type */
1607 encode_type (assembly, type, &buf);
1608 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1609 sigbuffer_free (&buf);
1614 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1619 sigbuffer_init (&buf, 32);
1621 sigbuffer_add_value (&buf, 0x06);
1622 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1623 /* encode custom attributes before the type */
1624 encode_reflection_type (assembly, fb->type, &buf);
1625 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1626 sigbuffer_free (&buf);
1631 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1632 char blob_size [64];
1633 char *b = blob_size;
1636 guint32 idx = 0, len = 0, dummy = 0;
1638 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1639 guint32 fpa_double [2];
1644 p = buf = g_malloc (64);
1646 *ret_type = MONO_TYPE_CLASS;
1648 box_val = (char*)&dummy;
1650 box_val = ((char*)val) + sizeof (MonoObject);
1651 *ret_type = val->vtable->klass->byval_arg.type;
1654 switch (*ret_type) {
1655 case MONO_TYPE_BOOLEAN:
1660 case MONO_TYPE_CHAR:
1677 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1678 fpa_p = (guint32*)box_val;
1679 fpa_double [0] = fpa_p [1];
1680 fpa_double [1] = fpa_p [0];
1681 box_val = (char*)fpa_double;
1685 case MONO_TYPE_VALUETYPE:
1686 if (val->vtable->klass->enumtype) {
1687 *ret_type = val->vtable->klass->enum_basetype->type;
1690 g_error ("we can't encode valuetypes");
1691 case MONO_TYPE_CLASS:
1693 case MONO_TYPE_STRING: {
1694 MonoString *str = (MonoString*)val;
1695 /* there is no signature */
1696 len = str->length * 2;
1697 mono_metadata_encode_value (len, b, &b);
1698 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1700 char *swapped = g_malloc (2 * mono_string_length (str));
1701 const char *p = (const char*)mono_string_chars (str);
1703 swap_with_size (swapped, p, 2, mono_string_length (str));
1704 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1708 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1714 case MONO_TYPE_GENERICINST:
1715 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1718 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1721 /* there is no signature */
1722 mono_metadata_encode_value (len, b, &b);
1723 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1724 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1725 swap_with_size (blob_size, box_val, len, 1);
1726 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1728 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1736 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1741 sigbuffer_init (&buf, 32);
1743 sigbuffer_add_value (&buf, minfo->type);
1745 switch (minfo->type) {
1746 case MONO_NATIVE_BYVALTSTR:
1747 case MONO_NATIVE_BYVALARRAY:
1748 sigbuffer_add_value (&buf, minfo->count);
1750 case MONO_NATIVE_LPARRAY:
1751 if (minfo->eltype || minfo->has_size) {
1752 sigbuffer_add_value (&buf, minfo->eltype);
1753 if (minfo->has_size) {
1754 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1755 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1757 /* LAMESPEC: ElemMult is undocumented */
1758 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1762 case MONO_NATIVE_CUSTOM:
1764 str = mono_string_to_utf8 (minfo->guid);
1766 sigbuffer_add_value (&buf, len);
1767 sigbuffer_add_mem (&buf, str, len);
1770 sigbuffer_add_value (&buf, 0);
1772 /* native type name */
1773 sigbuffer_add_value (&buf, 0);
1774 /* custom marshaler type name */
1775 if (minfo->marshaltype || minfo->marshaltyperef) {
1776 if (minfo->marshaltyperef)
1777 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1779 str = mono_string_to_utf8 (minfo->marshaltype);
1781 sigbuffer_add_value (&buf, len);
1782 sigbuffer_add_mem (&buf, str, len);
1785 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1786 sigbuffer_add_value (&buf, 0);
1788 if (minfo->mcookie) {
1789 str = mono_string_to_utf8 (minfo->mcookie);
1791 sigbuffer_add_value (&buf, len);
1792 sigbuffer_add_mem (&buf, str, len);
1795 sigbuffer_add_value (&buf, 0);
1801 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1802 sigbuffer_free (&buf);
1807 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1809 MonoDynamicTable *table;
1812 /* maybe this fixup should be done in the C# code */
1813 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1814 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1815 table = &assembly->tables [MONO_TABLE_FIELD];
1816 fb->table_idx = table->next_idx ++;
1817 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1818 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1819 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1820 values [MONO_FIELD_FLAGS] = fb->attrs;
1821 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1823 if (fb->offset != -1) {
1824 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1826 alloc_table (table, table->rows);
1827 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1828 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1829 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1831 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1832 guint32 field_type = 0;
1833 table = &assembly->tables [MONO_TABLE_CONSTANT];
1835 alloc_table (table, table->rows);
1836 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1837 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1838 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1839 values [MONO_CONSTANT_TYPE] = field_type;
1840 values [MONO_CONSTANT_PADDING] = 0;
1842 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1844 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1846 alloc_table (table, table->rows);
1847 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1848 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1850 * We store it in the code section because it's simpler for now.
1853 if (mono_array_length (fb->rva_data) >= 10)
1854 stream_data_align (&assembly->code);
1855 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1857 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1858 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1860 if (fb->marshal_info) {
1861 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1863 alloc_table (table, table->rows);
1864 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1865 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1866 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1871 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1874 guint32 nparams = 0;
1875 MonoReflectionMethodBuilder *mb = fb->get_method;
1876 MonoReflectionMethodBuilder *smb = fb->set_method;
1879 if (mb && mb->parameters)
1880 nparams = mono_array_length (mb->parameters);
1881 if (!mb && smb && smb->parameters)
1882 nparams = mono_array_length (smb->parameters) - 1;
1883 sigbuffer_init (&buf, 32);
1884 sigbuffer_add_byte (&buf, 0x08);
1885 sigbuffer_add_value (&buf, nparams);
1887 encode_reflection_type (assembly, mb->rtype, &buf);
1888 for (i = 0; i < nparams; ++i) {
1889 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1890 encode_reflection_type (assembly, pt, &buf);
1892 } else if (smb && smb->parameters) {
1893 /* the property type is the last param */
1894 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1895 for (i = 0; i < nparams; ++i) {
1896 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1897 encode_reflection_type (assembly, pt, &buf);
1900 encode_reflection_type (assembly, fb->type, &buf);
1903 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1904 sigbuffer_free (&buf);
1909 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1911 MonoDynamicTable *table;
1913 guint num_methods = 0;
1917 * we need to set things in the following tables:
1918 * PROPERTYMAP (info already filled in _get_type_info ())
1919 * PROPERTY (rows already preallocated in _get_type_info ())
1920 * METHOD (method info already done with the generic method code)
1923 table = &assembly->tables [MONO_TABLE_PROPERTY];
1924 pb->table_idx = table->next_idx ++;
1925 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1926 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1927 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1928 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1930 /* FIXME: we still don't handle 'other' methods */
1931 if (pb->get_method) num_methods ++;
1932 if (pb->set_method) num_methods ++;
1934 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1935 table->rows += num_methods;
1936 alloc_table (table, table->rows);
1938 if (pb->get_method) {
1939 semaidx = table->next_idx ++;
1940 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1941 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1942 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1943 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1945 if (pb->set_method) {
1946 semaidx = table->next_idx ++;
1947 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1948 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1949 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1950 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1955 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1957 MonoDynamicTable *table;
1959 guint num_methods = 0;
1963 * we need to set things in the following tables:
1964 * EVENTMAP (info already filled in _get_type_info ())
1965 * EVENT (rows already preallocated in _get_type_info ())
1966 * METHOD (method info already done with the generic method code)
1969 table = &assembly->tables [MONO_TABLE_EVENT];
1970 eb->table_idx = table->next_idx ++;
1971 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1972 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1973 values [MONO_EVENT_FLAGS] = eb->attrs;
1974 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1977 * FIXME: we still don't handle 'other' methods
1979 if (eb->add_method) num_methods ++;
1980 if (eb->remove_method) num_methods ++;
1981 if (eb->raise_method) num_methods ++;
1983 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1984 table->rows += num_methods;
1985 alloc_table (table, table->rows);
1987 if (eb->add_method) {
1988 semaidx = table->next_idx ++;
1989 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1990 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1991 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1992 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1994 if (eb->remove_method) {
1995 semaidx = table->next_idx ++;
1996 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1997 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1998 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1999 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2001 if (eb->raise_method) {
2002 semaidx = table->next_idx ++;
2003 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2004 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2005 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2006 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2011 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2013 MonoDynamicTable *table;
2014 guint32 num_constraints, i;
2018 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2019 num_constraints = gparam->iface_constraints ?
2020 mono_array_length (gparam->iface_constraints) : 0;
2021 table->rows += num_constraints;
2022 if (gparam->base_type)
2024 alloc_table (table, table->rows);
2026 if (gparam->base_type) {
2027 table_idx = table->next_idx ++;
2028 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2030 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2031 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2032 assembly, gparam->base_type->type);
2035 for (i = 0; i < num_constraints; i++) {
2036 MonoReflectionType *constraint = mono_array_get (
2037 gparam->iface_constraints, gpointer, i);
2039 table_idx = table->next_idx ++;
2040 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2042 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2043 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2044 assembly, constraint->type);
2049 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2051 GenericParamTableEntry *entry;
2054 * The GenericParam table must be sorted according to the `owner' field.
2055 * We need to do this sorting prior to writing the GenericParamConstraint
2056 * table, since we have to use the final GenericParam table indices there
2057 * and they must also be sorted.
2060 entry = g_new0 (GenericParamTableEntry, 1);
2061 entry->owner = owner;
2063 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2064 MONO_GC_REGISTER_ROOT (entry->gparam);
2066 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2068 g_ptr_array_add (assembly->gen_params, entry);
2072 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2074 MonoDynamicTable *table;
2075 MonoGenericParam *param;
2079 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2080 table_idx = table->next_idx ++;
2081 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2083 param = entry->gparam->type.type->data.generic_param;
2085 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2086 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2087 values [MONO_GENERICPARAM_NUMBER] = param->num;
2088 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2090 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2092 encode_constraints (entry->gparam, table_idx, assembly);
2096 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2098 MonoDynamicTable *table;
2101 guint32 cols [MONO_ASSEMBLY_SIZE];
2105 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2108 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2109 table = &assembly->tables [MONO_TABLE_MODULEREF];
2110 token = table->next_idx ++;
2112 alloc_table (table, table->rows);
2113 values = table->values + token * MONO_MODULEREF_SIZE;
2114 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2116 token <<= MONO_RESOLTION_SCOPE_BITS;
2117 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2118 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2123 if (image->assembly->dynamic)
2125 memset (cols, 0, sizeof (cols));
2127 /* image->assembly->image is the manifest module */
2128 image = image->assembly->image;
2129 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2132 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2133 token = table->next_idx ++;
2135 alloc_table (table, table->rows);
2136 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2137 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2138 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2139 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2140 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2141 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2142 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2143 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2144 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2146 if (strcmp ("", image->assembly->aname.culture)) {
2147 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2148 image->assembly->aname.culture);
2151 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2152 guchar pubtoken [9];
2154 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2155 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2157 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2159 token <<= MONO_RESOLTION_SCOPE_BITS;
2160 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2161 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2166 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2168 MonoDynamicTable *table;
2173 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2176 sigbuffer_init (&buf, 32);
2177 switch (type->type) {
2178 case MONO_TYPE_FNPTR:
2180 case MONO_TYPE_SZARRAY:
2181 case MONO_TYPE_ARRAY:
2183 case MONO_TYPE_MVAR:
2184 case MONO_TYPE_GENERICINST:
2185 encode_type (assembly, type, &buf);
2187 case MONO_TYPE_CLASS:
2188 case MONO_TYPE_VALUETYPE: {
2189 MonoClass *k = mono_class_from_mono_type (type);
2190 if (!k || !k->generic_container) {
2191 sigbuffer_free (&buf);
2194 encode_type (assembly, type, &buf);
2198 sigbuffer_free (&buf);
2202 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2203 if (assembly->save) {
2204 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2205 alloc_table (table, table->rows + 1);
2206 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2207 values [MONO_TYPESPEC_SIGNATURE] = token;
2209 sigbuffer_free (&buf);
2211 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2212 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2218 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2220 MonoDynamicTable *table;
2222 guint32 token, scope, enclosing;
2225 /* if the type requires a typespec, we must try that first*/
2226 if (try_typespec && (token = create_typespec (assembly, type)))
2228 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2231 klass = my_mono_class_from_mono_type (type);
2233 klass = mono_class_from_mono_type (type);
2236 * If it's in the same module and not a generic type parameter:
2238 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2239 (type->type != MONO_TYPE_MVAR)) {
2240 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2241 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2242 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2246 if (klass->nested_in) {
2247 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2248 /* get the typeref idx of the enclosing type */
2249 enclosing >>= MONO_TYPEDEFORREF_BITS;
2250 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2252 scope = resolution_scope_from_image (assembly, klass->image);
2254 table = &assembly->tables [MONO_TABLE_TYPEREF];
2255 if (assembly->save) {
2256 alloc_table (table, table->rows + 1);
2257 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2258 values [MONO_TYPEREF_SCOPE] = scope;
2259 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2260 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2262 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2263 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2265 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2270 * Despite the name, we handle also TypeSpec (with the above helper).
2273 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2275 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2279 * Insert a memberef row into the metadata: the token that point to the memberref
2280 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2281 * mono_image_get_fieldref_token()).
2282 * The sig param is an index to an already built signature.
2285 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2287 MonoDynamicTable *table;
2289 guint32 token, pclass;
2292 parent = mono_image_typedef_or_ref (assembly, type);
2293 switch (parent & MONO_TYPEDEFORREF_MASK) {
2294 case MONO_TYPEDEFORREF_TYPEREF:
2295 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2297 case MONO_TYPEDEFORREF_TYPESPEC:
2298 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2300 case MONO_TYPEDEFORREF_TYPEDEF:
2301 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2304 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2307 /* extract the index */
2308 parent >>= MONO_TYPEDEFORREF_BITS;
2310 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2312 if (assembly->save) {
2313 alloc_table (table, table->rows + 1);
2314 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2315 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2316 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2317 values [MONO_MEMBERREF_SIGNATURE] = sig;
2320 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2327 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2330 MonoMethodSignature *sig;
2332 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2337 * A methodref signature can't contain an unmanaged calling convention.
2339 sig = mono_metadata_signature_dup (mono_method_signature (method));
2340 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2341 sig->call_convention = MONO_CALL_DEFAULT;
2342 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2343 method->name, method_encode_signature (assembly, sig));
2345 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2350 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2351 const gchar *name, guint32 sig)
2353 MonoDynamicTable *table;
2357 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2359 if (assembly->save) {
2360 alloc_table (table, table->rows + 1);
2361 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2362 values [MONO_MEMBERREF_CLASS] = original;
2363 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2364 values [MONO_MEMBERREF_SIGNATURE] = sig;
2367 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2374 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2377 ReflectionMethodBuilder rmb;
2379 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2383 reflection_methodbuilder_from_method_builder (&rmb, mb);
2385 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2386 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2387 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2392 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2395 ReflectionMethodBuilder rmb;
2397 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2401 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2403 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2404 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2405 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2410 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2415 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2418 g_assert (f->field->parent);
2419 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2420 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2421 f->field->name, fieldref_encode_signature (assembly, type));
2422 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2427 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2431 guint32 nparams = context->method_inst->type_argc;
2434 if (!assembly->save)
2437 sigbuffer_init (&buf, 32);
2439 * FIXME: vararg, explicit_this, differenc call_conv values...
2441 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2442 sigbuffer_add_value (&buf, nparams);
2444 for (i = 0; i < nparams; i++)
2445 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2447 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2448 sigbuffer_free (&buf);
2453 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2455 MonoDynamicTable *table;
2457 guint32 token, mtoken = 0, sig;
2458 MonoMethodInflated *imethod;
2459 MonoMethod *declaring;
2461 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2463 g_assert (method->is_inflated);
2464 imethod = (MonoMethodInflated *) method;
2465 declaring = imethod->declaring;
2467 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2468 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2470 if (!mono_method_signature (declaring)->generic_param_count)
2473 switch (mono_metadata_token_table (mtoken)) {
2474 case MONO_TABLE_MEMBERREF:
2475 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2477 case MONO_TABLE_METHOD:
2478 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2481 g_assert_not_reached ();
2484 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2486 if (assembly->save) {
2487 alloc_table (table, table->rows + 1);
2488 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2489 values [MONO_METHODSPEC_METHOD] = mtoken;
2490 values [MONO_METHODSPEC_SIGNATURE] = sig;
2493 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2500 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2502 MonoMethodInflated *imethod;
2505 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2509 g_assert (method->is_inflated);
2510 imethod = (MonoMethodInflated *) method;
2512 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2513 token = method_encode_methodspec (assembly, method);
2515 guint32 sig = method_encode_signature (
2516 assembly, mono_method_signature (imethod->declaring));
2517 token = mono_image_get_memberref_token (
2518 assembly, &method->klass->byval_arg, method->name, sig);
2521 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2526 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2528 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2531 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2532 token = mono_image_get_memberref_token (
2533 assembly, &m->klass->byval_arg, m->name, sig);
2539 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2541 MonoDynamicTable *table;
2549 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2550 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2551 * Because of this, we must not insert it into the `typeref' hash table.
2554 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2558 sigbuffer_init (&buf, 32);
2560 g_assert (tb->generic_params);
2561 klass = mono_class_from_mono_type (tb->type.type);
2563 if (tb->generic_container)
2564 mono_reflection_create_generic_class (tb);
2566 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2567 g_assert (klass->generic_container);
2568 sigbuffer_add_value (&buf, klass->byval_arg.type);
2569 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2571 count = mono_array_length (tb->generic_params);
2572 sigbuffer_add_value (&buf, count);
2573 for (i = 0; i < count; i++) {
2574 MonoReflectionGenericParam *gparam;
2576 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2578 encode_type (assembly, gparam->type.type, &buf);
2581 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2583 if (assembly->save) {
2584 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2585 alloc_table (table, table->rows + 1);
2586 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2587 values [MONO_TYPESPEC_SIGNATURE] = token;
2589 sigbuffer_free (&buf);
2591 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2592 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2598 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2600 MonoDynamicTable *table;
2603 guint32 token, pclass, parent, sig;
2606 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2610 klass = mono_class_from_mono_type (fb->typeb->type);
2611 name = mono_string_to_utf8 (fb->name);
2613 sig = fieldref_encode_signature (assembly, fb->type->type);
2615 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2616 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2618 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2619 parent >>= MONO_TYPEDEFORREF_BITS;
2621 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2623 if (assembly->save) {
2624 alloc_table (table, table->rows + 1);
2625 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2626 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2627 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2628 values [MONO_MEMBERREF_SIGNATURE] = sig;
2631 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2633 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2638 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2645 if (!assembly->save)
2648 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2649 g_assert (helper->type == 2);
2651 if (helper->arguments)
2652 nargs = mono_array_length (helper->arguments);
2656 size = 10 + (nargs * 10);
2658 sigbuffer_init (&buf, 32);
2660 /* Encode calling convention */
2661 /* Change Any to Standard */
2662 if ((helper->call_conv & 0x03) == 0x03)
2663 helper->call_conv = 0x01;
2664 /* explicit_this implies has_this */
2665 if (helper->call_conv & 0x40)
2666 helper->call_conv &= 0x20;
2668 if (helper->call_conv == 0) { /* Unmanaged */
2669 idx = helper->unmanaged_call_conv - 1;
2672 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2673 if (helper->call_conv & 0x02) /* varargs */
2677 sigbuffer_add_byte (&buf, idx);
2678 sigbuffer_add_value (&buf, nargs);
2679 encode_reflection_type (assembly, helper->return_type, &buf);
2680 for (i = 0; i < nargs; ++i) {
2681 MonoArray *modreqs = NULL;
2682 MonoArray *modopts = NULL;
2683 MonoReflectionType *pt;
2685 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
2686 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
2687 if (helper->modopts && (i < mono_array_length (helper->modopts)))
2688 modopts = mono_array_get (helper->modopts, MonoArray*, i);
2690 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
2691 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2692 encode_reflection_type (assembly, pt, &buf);
2694 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2695 sigbuffer_free (&buf);
2701 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2704 MonoDynamicTable *table;
2707 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2708 idx = table->next_idx ++;
2710 alloc_table (table, table->rows);
2711 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2713 values [MONO_STAND_ALONE_SIGNATURE] =
2714 mono_reflection_encode_sighelper (assembly, helper);
2720 reflection_cc_to_file (int call_conv) {
2721 switch (call_conv & 0x3) {
2723 case 1: return MONO_CALL_DEFAULT;
2724 case 2: return MONO_CALL_VARARG;
2726 g_assert_not_reached ();
2733 MonoMethodSignature *sig;
2739 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2744 MonoMethodSignature *sig;
2747 name = mono_string_to_utf8 (m->name);
2748 nparams = mono_array_length (m->parameters);
2749 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2751 sig->sentinelpos = -1;
2752 sig->call_convention = reflection_cc_to_file (m->call_conv);
2753 sig->param_count = nparams;
2754 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2755 for (i = 0; i < nparams; ++i) {
2756 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2757 sig->params [i] = t->type;
2760 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2762 if (strcmp (name, am->name) == 0 &&
2763 mono_metadata_type_equal (am->parent, m->parent->type) &&
2764 mono_metadata_signature_equal (am->sig, sig)) {
2767 m->table_idx = am->token & 0xffffff;
2771 am = g_new0 (ArrayMethod, 1);
2774 am->parent = m->parent->type;
2775 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2776 method_encode_signature (assembly, sig));
2777 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2778 m->table_idx = am->token & 0xffffff;
2783 * Insert into the metadata tables all the info about the TypeBuilder tb.
2784 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2787 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2789 MonoDynamicTable *table;
2791 int i, is_object = 0, is_system = 0;
2794 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2795 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2796 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2797 n = mono_string_to_utf8 (tb->name);
2798 if (strcmp (n, "Object") == 0)
2800 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2802 n = mono_string_to_utf8 (tb->nspace);
2803 if (strcmp (n, "System") == 0)
2805 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2807 if (tb->parent && !(is_system && is_object) &&
2808 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2809 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2811 values [MONO_TYPEDEF_EXTENDS] = 0;
2813 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2814 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2817 * if we have explicitlayout or sequentiallayouts, output data in the
2818 * ClassLayout table.
2820 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2821 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2822 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2824 alloc_table (table, table->rows);
2825 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2826 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2827 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2828 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2831 /* handle interfaces */
2832 if (tb->interfaces) {
2833 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2835 table->rows += mono_array_length (tb->interfaces);
2836 alloc_table (table, table->rows);
2837 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2838 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2839 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2840 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2841 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2842 values += MONO_INTERFACEIMPL_SIZE;
2848 table = &assembly->tables [MONO_TABLE_FIELD];
2849 table->rows += tb->num_fields;
2850 alloc_table (table, table->rows);
2851 for (i = 0; i < tb->num_fields; ++i)
2852 mono_image_get_field_info (
2853 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2856 /* handle constructors */
2858 table = &assembly->tables [MONO_TABLE_METHOD];
2859 table->rows += mono_array_length (tb->ctors);
2860 alloc_table (table, table->rows);
2861 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2862 mono_image_get_ctor_info (domain,
2863 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2866 /* handle methods */
2868 table = &assembly->tables [MONO_TABLE_METHOD];
2869 table->rows += tb->num_methods;
2870 alloc_table (table, table->rows);
2871 for (i = 0; i < tb->num_methods; ++i)
2872 mono_image_get_method_info (
2873 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2876 /* Do the same with properties etc.. */
2877 if (tb->events && mono_array_length (tb->events)) {
2878 table = &assembly->tables [MONO_TABLE_EVENT];
2879 table->rows += mono_array_length (tb->events);
2880 alloc_table (table, table->rows);
2881 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2883 alloc_table (table, table->rows);
2884 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2885 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2886 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2887 for (i = 0; i < mono_array_length (tb->events); ++i)
2888 mono_image_get_event_info (
2889 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2891 if (tb->properties && mono_array_length (tb->properties)) {
2892 table = &assembly->tables [MONO_TABLE_PROPERTY];
2893 table->rows += mono_array_length (tb->properties);
2894 alloc_table (table, table->rows);
2895 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2897 alloc_table (table, table->rows);
2898 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2899 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2900 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2901 for (i = 0; i < mono_array_length (tb->properties); ++i)
2902 mono_image_get_property_info (
2903 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2906 /* handle generic parameters */
2907 if (tb->generic_params) {
2908 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2909 table->rows += mono_array_length (tb->generic_params);
2910 alloc_table (table, table->rows);
2911 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2912 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2914 mono_image_get_generic_param_info (
2915 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2919 mono_image_add_decl_security (assembly,
2920 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2923 MonoDynamicTable *ntable;
2925 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2926 ntable->rows += mono_array_length (tb->subtypes);
2927 alloc_table (ntable, ntable->rows);
2928 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2930 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2931 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2933 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2934 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2935 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2936 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2937 mono_string_to_utf8 (tb->name), tb->table_idx,
2938 ntable->next_idx, ntable->rows);*/
2939 values += MONO_NESTED_CLASS_SIZE;
2946 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2950 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2952 if (!type->subtypes)
2955 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2956 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2957 collect_types (types, subtype);
2962 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2964 if ((*type1)->table_idx < (*type2)->table_idx)
2967 if ((*type1)->table_idx > (*type2)->table_idx)
2974 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2979 for (i = 0; i < mono_array_length (pinfo); ++i) {
2980 MonoReflectionParamBuilder *pb;
2981 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2984 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2989 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2992 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2994 for (i = 0; i < tb->num_fields; ++i) {
2995 MonoReflectionFieldBuilder* fb;
2996 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2997 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3001 for (i = 0; i < mono_array_length (tb->events); ++i) {
3002 MonoReflectionEventBuilder* eb;
3003 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3004 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3007 if (tb->properties) {
3008 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3009 MonoReflectionPropertyBuilder* pb;
3010 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3011 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3015 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3016 MonoReflectionCtorBuilder* cb;
3017 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3018 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3019 params_add_cattrs (assembly, cb->pinfo);
3024 for (i = 0; i < tb->num_methods; ++i) {
3025 MonoReflectionMethodBuilder* mb;
3026 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3027 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3028 params_add_cattrs (assembly, mb->pinfo);
3033 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3034 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3039 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3043 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3045 if (moduleb->global_methods) {
3046 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3047 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3048 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3049 params_add_cattrs (assembly, mb->pinfo);
3053 if (moduleb->global_fields) {
3054 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3055 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3056 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3060 if (moduleb->types) {
3061 for (i = 0; i < moduleb->num_types; ++i)
3062 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3067 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3069 MonoDynamicTable *table;
3073 char *b = blob_size;
3076 table = &assembly->tables [MONO_TABLE_FILE];
3078 alloc_table (table, table->rows);
3079 values = table->values + table->next_idx * MONO_FILE_SIZE;
3080 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3081 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3082 if (module->image->dynamic) {
3083 /* This depends on the fact that the main module is emitted last */
3084 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3085 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3088 path = g_strdup (module->image->name);
3090 mono_sha1_get_digest_from_file (path, hash);
3093 mono_metadata_encode_value (20, b, &b);
3094 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3095 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3100 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3102 MonoDynamicTable *table;
3105 table = &assembly->tables [MONO_TABLE_MODULE];
3106 mb->table_idx = table->next_idx ++;
3107 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3108 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3111 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3112 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3113 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3114 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3118 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3119 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3121 MonoDynamicTable *table;
3125 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3126 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3129 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3131 alloc_table (table, table->rows);
3132 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3134 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3135 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3136 if (klass->nested_in)
3137 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3139 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3140 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3141 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3143 res = table->next_idx;
3147 /* Emit nested types */
3148 if (klass->nested_classes) {
3151 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3152 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3159 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3160 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3165 klass = mono_class_from_mono_type (tb->type.type);
3167 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3169 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3170 parent_index, assembly);
3174 * We need to do this ourselves since klass->nested_classes is not set up.
3177 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3178 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3183 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3184 guint32 module_index, MonoDynamicImage *assembly)
3186 MonoImage *image = module->image;
3190 t = &image->tables [MONO_TABLE_TYPEDEF];
3192 for (i = 0; i < t->rows; ++i) {
3193 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3195 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3196 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3201 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3203 MonoDynamicTable *table;
3209 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3211 if (assemblyb->type_forwarders) {
3212 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3213 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3219 klass = mono_class_from_mono_type (t->type);
3221 scope = resolution_scope_from_image (assembly, klass->image);
3222 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3223 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3226 alloc_table (table, table->rows);
3227 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3229 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3230 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3231 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3232 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3233 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3238 #define align_pointer(base,p)\
3240 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3242 (p) += 4 - (__diff & 3);\
3246 compare_constants (const void *a, const void *b)
3248 const guint32 *a_values = a;
3249 const guint32 *b_values = b;
3250 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3254 compare_semantics (const void *a, const void *b)
3256 const guint32 *a_values = a;
3257 const guint32 *b_values = b;
3258 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3261 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3265 compare_custom_attrs (const void *a, const void *b)
3267 const guint32 *a_values = a;
3268 const guint32 *b_values = b;
3270 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3274 compare_field_marshal (const void *a, const void *b)
3276 const guint32 *a_values = a;
3277 const guint32 *b_values = b;
3279 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3283 compare_nested (const void *a, const void *b)
3285 const guint32 *a_values = a;
3286 const guint32 *b_values = b;
3288 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3292 compare_genericparam (const void *a, const void *b)
3294 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3295 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3297 if ((*b_entry)->owner == (*a_entry)->owner)
3299 (*a_entry)->gparam->type.type->data.generic_param->num -
3300 (*b_entry)->gparam->type.type->data.generic_param->num;
3302 return (*a_entry)->owner - (*b_entry)->owner;
3306 compare_declsecurity_attrs (const void *a, const void *b)
3308 const guint32 *a_values = a;
3309 const guint32 *b_values = b;
3311 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3315 pad_heap (MonoDynamicStream *sh)
3317 if (sh->index & 3) {
3318 int sz = 4 - (sh->index & 3);
3319 memset (sh->data + sh->index, 0, sz);
3326 MonoDynamicStream *stream;
3330 * build_compressed_metadata() fills in the blob of data that represents the
3331 * raw metadata as it will be saved in the PE file. The five streams are output
3332 * and the metadata tables are comnpressed from the guint32 array representation,
3333 * to the compressed on-disk format.
3336 build_compressed_metadata (MonoDynamicImage *assembly)
3338 MonoDynamicTable *table;
3340 guint64 valid_mask = 0;
3341 guint64 sorted_mask;
3342 guint32 heapt_size = 0;
3343 guint32 meta_size = 256; /* allow for header and other stuff */
3344 guint32 table_offset;
3345 guint32 ntables = 0;
3351 struct StreamDesc stream_desc [5];
3353 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3354 for (i = 0; i < assembly->gen_params->len; i++){
3355 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3356 write_generic_param_entry (assembly, entry);
3359 stream_desc [0].name = "#~";
3360 stream_desc [0].stream = &assembly->tstream;
3361 stream_desc [1].name = "#Strings";
3362 stream_desc [1].stream = &assembly->sheap;
3363 stream_desc [2].name = "#US";
3364 stream_desc [2].stream = &assembly->us;
3365 stream_desc [3].name = "#Blob";
3366 stream_desc [3].stream = &assembly->blob;
3367 stream_desc [4].name = "#GUID";
3368 stream_desc [4].stream = &assembly->guid;
3370 /* tables that are sorted */
3371 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3372 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3373 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3374 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3375 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3376 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3378 /* Compute table sizes */
3379 /* the MonoImage has already been created in mono_image_basic_init() */
3380 meta = &assembly->image;
3382 /* sizes should be multiple of 4 */
3383 pad_heap (&assembly->blob);
3384 pad_heap (&assembly->guid);
3385 pad_heap (&assembly->sheap);
3386 pad_heap (&assembly->us);
3388 /* Setup the info used by compute_sizes () */
3389 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3390 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3391 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3393 meta_size += assembly->blob.index;
3394 meta_size += assembly->guid.index;
3395 meta_size += assembly->sheap.index;
3396 meta_size += assembly->us.index;
3398 for (i=0; i < MONO_TABLE_NUM; ++i)
3399 meta->tables [i].rows = assembly->tables [i].rows;
3401 for (i = 0; i < MONO_TABLE_NUM; i++){
3402 if (meta->tables [i].rows == 0)
3404 valid_mask |= (guint64)1 << i;
3406 meta->tables [i].row_size = mono_metadata_compute_size (
3407 meta, i, &meta->tables [i].size_bitfield);
3408 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3410 heapt_size += 24; /* #~ header size */
3411 heapt_size += ntables * 4;
3412 /* make multiple of 4 */
3415 meta_size += heapt_size;
3416 meta->raw_metadata = g_malloc0 (meta_size);
3417 p = (unsigned char*)meta->raw_metadata;
3418 /* the metadata signature */
3419 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3420 /* version numbers and 4 bytes reserved */
3421 int16val = (guint16*)p;
3422 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3423 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3425 /* version string */
3426 int32val = (guint32*)p;
3427 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3429 memcpy (p, meta->version, strlen (meta->version));
3430 p += GUINT32_FROM_LE (*int32val);
3431 align_pointer (meta->raw_metadata, p);
3432 int16val = (guint16*)p;
3433 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3434 *int16val = GUINT16_TO_LE (5); /* number of streams */
3438 * write the stream info.
3440 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3441 table_offset += 3; table_offset &= ~3;
3443 assembly->tstream.index = heapt_size;
3444 for (i = 0; i < 5; ++i) {
3445 int32val = (guint32*)p;
3446 stream_desc [i].stream->offset = table_offset;
3447 *int32val++ = GUINT32_TO_LE (table_offset);
3448 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3449 table_offset += GUINT32_FROM_LE (*int32val);
3450 table_offset += 3; table_offset &= ~3;
3452 strcpy ((char*)p, stream_desc [i].name);
3453 p += strlen (stream_desc [i].name) + 1;
3454 align_pointer (meta->raw_metadata, p);
3457 * now copy the data, the table stream header and contents goes first.
3459 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3460 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3461 int32val = (guint32*)p;
3462 *int32val = GUINT32_TO_LE (0); /* reserved */
3465 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3466 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3467 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3468 *p++ = 2; /* version */
3471 *p++ = 1; /* version */
3475 if (meta->idx_string_wide)
3477 if (meta->idx_guid_wide)
3479 if (meta->idx_blob_wide)
3482 *p++ = 1; /* reserved */
3483 int64val = (guint64*)p;
3484 *int64val++ = GUINT64_TO_LE (valid_mask);
3485 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3487 int32val = (guint32*)p;
3488 for (i = 0; i < MONO_TABLE_NUM; i++){
3489 if (meta->tables [i].rows == 0)
3491 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3493 p = (unsigned char*)int32val;
3495 /* sort the tables that still need sorting */
3496 table = &assembly->tables [MONO_TABLE_CONSTANT];
3498 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3499 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3501 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3502 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3504 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3505 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3507 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3508 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3510 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3511 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3512 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3514 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3516 /* compress the tables */
3517 for (i = 0; i < MONO_TABLE_NUM; i++){
3520 guint32 bitfield = meta->tables [i].size_bitfield;
3521 if (!meta->tables [i].rows)
3523 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3524 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3525 meta->tables [i].base = (char*)p;
3526 for (row = 1; row <= meta->tables [i].rows; ++row) {
3527 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3528 for (col = 0; col < assembly->tables [i].columns; ++col) {
3529 switch (mono_metadata_table_size (bitfield, col)) {
3531 *p++ = values [col];
3534 *p++ = values [col] & 0xff;
3535 *p++ = (values [col] >> 8) & 0xff;
3538 *p++ = values [col] & 0xff;
3539 *p++ = (values [col] >> 8) & 0xff;
3540 *p++ = (values [col] >> 16) & 0xff;
3541 *p++ = (values [col] >> 24) & 0xff;
3544 g_assert_not_reached ();
3548 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3551 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3552 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3553 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3554 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3555 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3557 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3561 * Some tables in metadata need to be sorted according to some criteria, but
3562 * when methods and fields are first created with reflection, they may be assigned a token
3563 * that doesn't correspond to the final token they will get assigned after the sorting.
3564 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3565 * with the reflection objects that represent them. Once all the tables are set up, the
3566 * reflection objects will contains the correct table index. fixup_method() will fixup the
3567 * tokens for the method with ILGenerator @ilgen.
3570 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3571 guint32 code_idx = GPOINTER_TO_UINT (value);
3572 MonoReflectionILTokenInfo *iltoken;
3573 MonoReflectionFieldBuilder *field;
3574 MonoReflectionCtorBuilder *ctor;
3575 MonoReflectionMethodBuilder *method;
3576 MonoReflectionTypeBuilder *tb;
3577 MonoReflectionArrayMethod *am;
3579 unsigned char *target;
3581 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3582 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3583 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3584 switch (target [3]) {
3585 case MONO_TABLE_FIELD:
3586 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3587 field = (MonoReflectionFieldBuilder *)iltoken->member;
3588 idx = field->table_idx;
3589 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3590 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3591 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3593 g_assert_not_reached ();
3596 case MONO_TABLE_METHOD:
3597 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3598 method = (MonoReflectionMethodBuilder *)iltoken->member;
3599 idx = method->table_idx;
3600 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3601 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3602 idx = ctor->table_idx;
3603 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3604 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3605 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3606 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3608 g_assert_not_reached ();
3611 case MONO_TABLE_TYPEDEF:
3612 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3613 g_assert_not_reached ();
3614 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3615 idx = tb->table_idx;
3617 case MONO_TABLE_MEMBERREF:
3618 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3619 am = (MonoReflectionArrayMethod*)iltoken->member;
3620 idx = am->table_idx;
3621 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3622 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3623 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3624 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3625 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3626 g_assert (m->klass->generic_class || m->klass->generic_container);
3628 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3630 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3631 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3632 g_assert (f->generic_info);
3634 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3635 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3638 g_assert_not_reached ();
3641 case MONO_TABLE_METHODSPEC:
3642 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3643 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3644 g_assert (mono_method_signature (m)->generic_param_count);
3647 g_assert_not_reached ();
3651 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3653 target [0] = idx & 0xff;
3654 target [1] = (idx >> 8) & 0xff;
3655 target [2] = (idx >> 16) & 0xff;
3662 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3663 * value is not known when the table is emitted.
3666 fixup_cattrs (MonoDynamicImage *assembly)
3668 MonoDynamicTable *table;
3670 guint32 type, i, idx, token;
3673 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3675 for (i = 0; i < table->rows; ++i) {
3676 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3678 type = values [MONO_CUSTOM_ATTR_TYPE];
3679 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3680 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3681 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3682 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3685 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3686 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3687 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3688 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3695 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3697 MonoDynamicTable *table;
3700 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3702 alloc_table (table, table->rows);
3703 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3704 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3705 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3706 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3707 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3712 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3714 MonoDynamicTable *table;
3718 char *b = blob_size;
3720 guint32 idx, offset;
3722 if (rsrc->filename) {
3723 name = mono_string_to_utf8 (rsrc->filename);
3724 sname = g_path_get_basename (name);
3726 table = &assembly->tables [MONO_TABLE_FILE];
3728 alloc_table (table, table->rows);
3729 values = table->values + table->next_idx * MONO_FILE_SIZE;
3730 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3731 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3734 mono_sha1_get_digest_from_file (name, hash);
3735 mono_metadata_encode_value (20, b, &b);
3736 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3737 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3739 idx = table->next_idx++;
3741 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3747 data = mono_array_addr (rsrc->data, char, 0);
3748 len = mono_array_length (rsrc->data);
3754 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3755 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3756 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3757 mono_image_add_stream_data (&assembly->resources, data, len);
3761 * The entry should be emitted into the MANIFESTRESOURCE table of
3762 * the main module, but that needs to reference the FILE table
3763 * which isn't emitted yet.
3770 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3774 set_version_from_string (MonoString *version, guint32 *values)
3776 gchar *ver, *p, *str;
3779 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3780 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3781 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3782 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3785 ver = str = mono_string_to_utf8 (version);
3786 for (i = 0; i < 4; ++i) {
3787 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3793 /* handle Revision and Build */
3803 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3807 char *b = blob_size;
3812 len = mono_array_length (pkey);
3813 mono_metadata_encode_value (len, b, &b);
3814 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3815 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
3817 assembly->public_key = g_malloc (len);
3818 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
3819 assembly->public_key_len = len;
3821 /* Special case: check for ECMA key (16 bytes) */
3822 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
3823 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3824 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3825 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3826 /* minimum key size (in 2.0) is 384 bits */
3827 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3829 /* FIXME - verifier */
3830 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3831 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3833 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3839 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3841 MonoDynamicTable *table;
3842 MonoDynamicImage *assembly;
3843 MonoReflectionAssemblyBuilder *assemblyb;
3847 guint32 module_index;
3849 assemblyb = moduleb->assemblyb;
3850 assembly = moduleb->dynamic_image;
3851 domain = mono_object_domain (assemblyb);
3853 /* Emit ASSEMBLY table */
3854 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3855 alloc_table (table, 1);
3856 values = table->values + MONO_ASSEMBLY_SIZE;
3857 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3858 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3859 if (assemblyb->culture) {
3860 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3862 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3864 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3865 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3866 set_version_from_string (assemblyb->version, values);
3868 /* Emit FILE + EXPORTED_TYPE table */
3870 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3872 MonoReflectionModuleBuilder *file_module =
3873 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3874 if (file_module != moduleb) {
3875 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3877 if (file_module->types) {
3878 for (j = 0; j < file_module->num_types; ++j) {
3879 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3880 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3885 if (assemblyb->loaded_modules) {
3886 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3887 MonoReflectionModule *file_module =
3888 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3889 mono_image_fill_file_table (domain, file_module, assembly);
3891 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3894 if (assemblyb->type_forwarders)
3895 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3897 /* Emit MANIFESTRESOURCE table */
3899 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3901 MonoReflectionModuleBuilder *file_module =
3902 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3903 /* The table for the main module is emitted later */
3904 if (file_module != moduleb) {
3906 if (file_module->resources) {
3907 int len = mono_array_length (file_module->resources);
3908 for (j = 0; j < len; ++j) {
3909 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3910 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3918 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3919 * for the modulebuilder @moduleb.
3920 * At the end of the process, method and field tokens are fixed up and the
3921 * on-disk compressed metadata representation is created.
3924 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3926 MonoDynamicTable *table;
3927 MonoDynamicImage *assembly;
3928 MonoReflectionAssemblyBuilder *assemblyb;
3934 assemblyb = moduleb->assemblyb;
3935 assembly = moduleb->dynamic_image;
3936 domain = mono_object_domain (assemblyb);
3938 if (assembly->text_rva)
3941 assembly->text_rva = START_TEXT_RVA;
3943 if (moduleb->is_main) {
3944 mono_image_emit_manifest (moduleb);
3947 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3948 table->rows = 1; /* .<Module> */
3950 alloc_table (table, table->rows);
3952 * Set the first entry.
3954 values = table->values + table->columns;
3955 values [MONO_TYPEDEF_FLAGS] = 0;
3956 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3957 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3958 values [MONO_TYPEDEF_EXTENDS] = 0;
3959 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3960 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3963 * handle global methods
3964 * FIXME: test what to do when global methods are defined in multiple modules.
3966 if (moduleb->global_methods) {
3967 table = &assembly->tables [MONO_TABLE_METHOD];
3968 table->rows += mono_array_length (moduleb->global_methods);
3969 alloc_table (table, table->rows);
3970 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3971 mono_image_get_method_info (
3972 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3974 if (moduleb->global_fields) {
3975 table = &assembly->tables [MONO_TABLE_FIELD];
3976 table->rows += mono_array_length (moduleb->global_fields);
3977 alloc_table (table, table->rows);
3978 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3979 mono_image_get_field_info (
3980 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3983 table = &assembly->tables [MONO_TABLE_MODULE];
3984 alloc_table (table, 1);
3985 mono_image_fill_module_table (domain, moduleb, assembly);
3987 /* Collect all types into a list sorted by their table_idx */
3988 types = g_ptr_array_new ();
3991 for (i = 0; i < moduleb->num_types; ++i) {
3992 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3993 collect_types (types, type);
3996 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3997 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3998 table->rows += types->len;
3999 alloc_table (table, table->rows);
4002 * Emit type names + namespaces at one place inside the string heap,
4003 * so load_class_names () needs to touch fewer pages.
4005 for (i = 0; i < types->len; ++i) {
4006 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4007 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4009 for (i = 0; i < types->len; ++i) {
4010 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4011 string_heap_insert_mstring (&assembly->sheap, tb->name);
4014 for (i = 0; i < types->len; ++i) {
4015 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4016 mono_image_get_type_info (domain, type, assembly);
4020 * table->rows is already set above and in mono_image_fill_module_table.
4022 /* add all the custom attributes at the end, once all the indexes are stable */
4023 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4025 /* CAS assembly permissions */
4026 if (assemblyb->permissions_minimum)
4027 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4028 if (assemblyb->permissions_optional)
4029 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4030 if (assemblyb->permissions_refused)
4031 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4033 module_add_cattrs (assembly, moduleb);
4036 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4038 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4039 * the final tokens and don't need another fixup pass. */
4041 if (moduleb->global_methods) {
4042 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4043 MonoReflectionMethodBuilder *mb = mono_array_get (
4044 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4045 mono_image_add_methodimpl (assembly, mb);
4049 for (i = 0; i < types->len; ++i) {
4050 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4051 if (type->methods) {
4052 for (j = 0; j < type->num_methods; ++j) {
4053 MonoReflectionMethodBuilder *mb = mono_array_get (
4054 type->methods, MonoReflectionMethodBuilder*, j);
4056 mono_image_add_methodimpl (assembly, mb);
4061 g_ptr_array_free (types, TRUE);
4063 fixup_cattrs (assembly);
4067 * mono_image_insert_string:
4068 * @module: module builder object
4071 * Insert @str into the user string stream of @module.
4074 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4076 MonoDynamicImage *assembly;
4081 MONO_ARCH_SAVE_REGS;
4083 if (!module->dynamic_image)
4084 mono_image_module_basic_init (module);
4086 assembly = module->dynamic_image;
4088 if (assembly->save) {
4089 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4090 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4091 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4093 char *swapped = g_malloc (2 * mono_string_length (str));
4094 const char *p = (const char*)mono_string_chars (str);
4096 swap_with_size (swapped, p, 2, mono_string_length (str));
4097 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4101 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4103 mono_image_add_stream_data (&assembly->us, "", 1);
4105 idx = assembly->us.index ++;
4108 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4110 return MONO_TOKEN_STRING | idx;
4114 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4119 klass = obj->vtable->klass;
4120 if (strcmp (klass->name, "MonoMethod") == 0) {
4121 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4122 MonoMethodSignature *sig, *old;
4123 guint32 sig_token, parent;
4126 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4128 nargs = mono_array_length (opt_param_types);
4129 old = mono_method_signature (method);
4130 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4132 sig->hasthis = old->hasthis;
4133 sig->explicit_this = old->explicit_this;
4134 sig->call_convention = old->call_convention;
4135 sig->generic_param_count = old->generic_param_count;
4136 sig->param_count = old->param_count + nargs;
4137 sig->sentinelpos = old->param_count;
4138 sig->ret = old->ret;
4140 for (i = 0; i < old->param_count; i++)
4141 sig->params [i] = old->params [i];
4143 for (i = 0; i < nargs; i++) {
4144 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4145 sig->params [old->param_count + i] = rt->type;
4148 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4149 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4150 parent >>= MONO_TYPEDEFORREF_BITS;
4152 parent <<= MONO_MEMBERREF_PARENT_BITS;
4153 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4155 sig_token = method_encode_signature (assembly, sig);
4156 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4157 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4158 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4159 ReflectionMethodBuilder rmb;
4160 guint32 parent, sig;
4162 reflection_methodbuilder_from_method_builder (&rmb, mb);
4163 rmb.opt_types = opt_param_types;
4165 sig = method_builder_encode_signature (assembly, &rmb);
4167 parent = mono_image_create_token (assembly, obj, TRUE);
4168 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4170 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4171 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4173 token = mono_image_get_varargs_method_token (
4174 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4176 g_error ("requested method token for %s\n", klass->name);
4183 * mono_image_create_token:
4184 * @assembly: a dynamic assembly
4187 * Get a token to insert in the IL code stream for the given MemberInfo.
4188 * @obj can be one of:
4189 * ConstructorBuilder
4192 * GenericTypeParameterBuilder
4200 * MonoGenericCMethod
4206 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4211 klass = obj->vtable->klass;
4212 if (strcmp (klass->name, "MethodBuilder") == 0) {
4213 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4214 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4216 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4217 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4219 token = mono_image_get_methodbuilder_token (assembly, mb);
4220 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4221 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4222 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4223 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4225 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4226 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4228 token = mono_image_get_ctorbuilder_token (assembly, mb);
4229 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4230 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4231 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4232 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4233 if (tb->generic_params) {
4234 token = mono_image_get_generic_field_token (assembly, fb);
4236 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4238 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4239 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4240 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4241 } else if (strcmp (klass->name, "MonoType") == 0) {
4242 MonoReflectionType *tb = (MonoReflectionType *)obj;
4243 MonoClass *mc = mono_class_from_mono_type (tb->type);
4244 token = mono_metadata_token_from_dor (
4245 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4246 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4247 MonoReflectionType *tb = (MonoReflectionType *)obj;
4248 token = mono_metadata_token_from_dor (
4249 mono_image_typedef_or_ref (assembly, tb->type));
4250 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4251 MonoReflectionType *tb = (MonoReflectionType *)obj;
4252 token = mono_metadata_token_from_dor (
4253 mono_image_typedef_or_ref (assembly, tb->type));
4254 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4255 strcmp (klass->name, "MonoMethod") == 0 ||
4256 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4257 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4258 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4259 if (m->method->is_inflated) {
4260 if (create_methodspec)
4261 token = mono_image_get_methodspec_token (assembly, m->method);
4263 token = mono_image_get_inflated_method_token (assembly, m->method);
4264 } else if ((m->method->klass->image == &assembly->image) &&
4265 !m->method->klass->generic_class) {
4266 static guint32 method_table_idx = 0xffffff;
4267 if (m->method->klass->wastypebuilder) {
4268 /* we use the same token as the one that was assigned
4269 * to the Methodbuilder.
4270 * FIXME: do the equivalent for Fields.
4272 token = m->method->token;
4275 * Each token should have a unique index, but the indexes are
4276 * assigned by managed code, so we don't know about them. An
4277 * easy solution is to count backwards...
4279 method_table_idx --;
4280 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4283 token = mono_image_get_methodref_token (assembly, m->method);
4285 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4286 } else if (strcmp (klass->name, "MonoField") == 0) {
4287 MonoReflectionField *f = (MonoReflectionField *)obj;
4288 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4289 static guint32 field_table_idx = 0xffffff;
4291 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4293 token = mono_image_get_fieldref_token (assembly, f);
4295 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4296 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4297 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4298 token = mono_image_get_array_token (assembly, m);
4299 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4300 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4301 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4302 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4303 MonoReflectionType *tb = (MonoReflectionType *)obj;
4304 token = mono_metadata_token_from_dor (
4305 mono_image_typedef_or_ref (assembly, tb->type));
4307 g_error ("requested token for %s\n", klass->name);
4310 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4316 guint32 import_lookup_table;
4320 guint32 import_address_table_rva;
4328 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4330 static MonoDynamicImage*
4331 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4333 static const guchar entrycode [16] = {0xff, 0x25, 0};
4334 MonoDynamicImage *image;
4337 const char *version = mono_get_runtime_info ()->runtime_version;
4340 image = GC_MALLOC (sizeof (MonoDynamicImage));
4342 image = g_new0 (MonoDynamicImage, 1);
4345 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4347 /*g_print ("created image %p\n", image);*/
4348 /* keep in sync with image.c */
4349 image->image.name = assembly_name;
4350 image->image.assembly_name = image->image.name; /* they may be different */
4351 image->image.module_name = module_name;
4352 image->image.version = g_strdup (version);
4353 image->image.md_version_major = 1;
4354 image->image.md_version_minor = 1;
4355 image->image.dynamic = TRUE;
4357 image->image.references = g_new0 (MonoAssembly*, 1);
4358 image->image.references [0] = NULL;
4360 mono_image_init (&image->image);
4362 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4363 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4364 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4365 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4366 image->handleref = g_hash_table_new (NULL, NULL);
4367 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4368 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4369 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4370 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4371 image->gen_params = g_ptr_array_new ();
4373 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4374 string_heap_init (&image->sheap);
4375 mono_image_add_stream_data (&image->us, "", 1);
4376 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4377 /* import tables... */
4378 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4379 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4380 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4381 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4382 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4383 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4384 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4385 stream_data_align (&image->code);
4387 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4389 for (i=0; i < MONO_TABLE_NUM; ++i) {
4390 image->tables [i].next_idx = 1;
4391 image->tables [i].columns = table_sizes [i];
4394 image->image.assembly = (MonoAssembly*)assembly;
4395 image->run = assembly->run;
4396 image->save = assembly->save;
4397 image->pe_kind = 0x1; /* ILOnly */
4398 image->machine = 0x14c; /* I386 */
4400 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4406 * mono_image_basic_init:
4407 * @assembly: an assembly builder object
4409 * Create the MonoImage that represents the assembly builder and setup some
4410 * of the helper hash table and the basic metadata streams.
4413 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4415 MonoDynamicAssembly *assembly;
4416 MonoDynamicImage *image;
4417 MonoDomain *domain = mono_object_domain (assemblyb);
4419 MONO_ARCH_SAVE_REGS;
4421 if (assemblyb->dynamic_assembly)
4425 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4427 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4430 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4432 assembly->assembly.ref_count = 1;
4433 assembly->assembly.dynamic = TRUE;
4434 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4435 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4436 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4437 if (assemblyb->culture)
4438 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4440 assembly->assembly.aname.culture = g_strdup ("");
4442 if (assemblyb->version) {
4443 char *vstr = mono_string_to_utf8 (assemblyb->version);
4444 char **version = g_strsplit (vstr, ".", 4);
4445 char **parts = version;
4446 assembly->assembly.aname.major = atoi (*parts++);
4447 assembly->assembly.aname.minor = atoi (*parts++);
4448 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4449 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4451 g_strfreev (version);
4454 assembly->assembly.aname.major = 0;
4455 assembly->assembly.aname.minor = 0;
4456 assembly->assembly.aname.build = 0;
4457 assembly->assembly.aname.revision = 0;
4460 assembly->run = assemblyb->access != 2;
4461 assembly->save = assemblyb->access != 1;
4463 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4464 image->initial_image = TRUE;
4465 assembly->assembly.aname.name = image->image.name;
4466 assembly->assembly.image = &image->image;
4468 mono_domain_assemblies_lock (domain);
4469 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4470 mono_domain_assemblies_unlock (domain);
4472 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4474 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4476 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4480 calc_section_size (MonoDynamicImage *assembly)
4484 /* alignment constraints */
4485 assembly->code.index += 3;
4486 assembly->code.index &= ~3;
4487 assembly->meta_size += 3;
4488 assembly->meta_size &= ~3;
4489 assembly->resources.index += 3;
4490 assembly->resources.index &= ~3;
4492 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4493 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4496 if (assembly->win32_res) {
4497 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4499 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4500 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4504 assembly->sections [MONO_SECTION_RELOC].size = 12;
4505 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4515 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4519 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4521 ResTreeNode *t1 = (ResTreeNode*)a;
4522 ResTreeNode *t2 = (ResTreeNode*)b;
4524 return t1->id - t2->id;
4528 * resource_tree_create:
4530 * Organize the resources into a resource tree.
4532 static ResTreeNode *
4533 resource_tree_create (MonoArray *win32_resources)
4535 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4539 tree = g_new0 (ResTreeNode, 1);
4541 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4542 MonoReflectionWin32Resource *win32_res =
4543 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4547 /* FIXME: BUG: this stores managed references in unmanaged memory */
4548 lang_node = g_new0 (ResTreeNode, 1);
4549 lang_node->id = win32_res->lang_id;
4550 lang_node->win32_res = win32_res;
4552 /* Create type node if neccesary */
4554 for (l = tree->children; l; l = l->next)
4555 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4556 type_node = (ResTreeNode*)l->data;
4561 type_node = g_new0 (ResTreeNode, 1);
4562 type_node->id = win32_res->res_type;
4565 * The resource types have to be sorted otherwise
4566 * Windows Explorer can't display the version information.
4568 tree->children = g_slist_insert_sorted (tree->children,
4569 type_node, resource_tree_compare_by_id);
4572 /* Create res node if neccesary */
4574 for (l = type_node->children; l; l = l->next)
4575 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4576 res_node = (ResTreeNode*)l->data;
4581 res_node = g_new0 (ResTreeNode, 1);
4582 res_node->id = win32_res->res_id;
4583 type_node->children = g_slist_append (type_node->children, res_node);
4586 res_node->children = g_slist_append (res_node->children, lang_node);
4593 * resource_tree_encode:
4595 * Encode the resource tree into the format used in the PE file.
4598 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4601 MonoPEResourceDir dir;
4602 MonoPEResourceDirEntry dir_entry;
4603 MonoPEResourceDataEntry data_entry;
4607 * For the format of the resource directory, see the article
4608 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4612 memset (&dir, 0, sizeof (dir));
4613 memset (&dir_entry, 0, sizeof (dir_entry));
4614 memset (&data_entry, 0, sizeof (data_entry));
4616 g_assert (sizeof (dir) == 16);
4617 g_assert (sizeof (dir_entry) == 8);
4618 g_assert (sizeof (data_entry) == 16);
4620 node->offset = p - begin;
4622 /* IMAGE_RESOURCE_DIRECTORY */
4623 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4625 memcpy (p, &dir, sizeof (dir));
4628 /* Reserve space for entries */
4630 p += sizeof (dir_entry) * dir.res_id_entries;
4632 /* Write children */
4633 for (l = node->children; l; l = l->next) {
4634 ResTreeNode *child = (ResTreeNode*)l->data;
4636 if (child->win32_res) {
4638 child->offset = p - begin;
4640 /* IMAGE_RESOURCE_DATA_ENTRY */
4641 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4642 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4644 memcpy (p, &data_entry, sizeof (data_entry));
4645 p += sizeof (data_entry);
4647 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4648 p += data_entry.rde_size;
4650 resource_tree_encode (child, begin, p, &p);
4654 /* IMAGE_RESOURCE_ENTRY */
4655 for (l = node->children; l; l = l->next) {
4656 ResTreeNode *child = (ResTreeNode*)l->data;
4657 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4659 dir_entry.is_dir = child->win32_res ? 0 : 1;
4660 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4662 memcpy (entries, &dir_entry, sizeof (dir_entry));
4663 entries += sizeof (dir_entry);
4670 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4675 MonoReflectionWin32Resource *win32_res;
4678 if (!assemblyb->win32_resources)
4682 * Resources are stored in a three level tree inside the PE file.
4683 * - level one contains a node for each type of resource
4684 * - level two contains a node for each resource
4685 * - level three contains a node for each instance of a resource for a
4686 * specific language.
4689 tree = resource_tree_create (assemblyb->win32_resources);
4691 /* Estimate the size of the encoded tree */
4693 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4694 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4695 size += mono_array_length (win32_res->res_data);
4697 /* Directory structure */
4698 size += mono_array_length (assemblyb->win32_resources) * 256;
4699 p = buf = g_malloc (size);
4701 resource_tree_encode (tree, p, p, &p);
4703 g_assert (p - buf <= size);
4705 assembly->win32_res = g_malloc (p - buf);
4706 assembly->win32_res_size = p - buf;
4707 memcpy (assembly->win32_res, buf, p - buf);
4713 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4715 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4718 p += sizeof (MonoPEResourceDir);
4719 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4720 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4721 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4722 if (dir_entry->is_dir) {
4723 fixup_resource_directory (res_section, child, rva);
4725 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4726 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4729 p += sizeof (MonoPEResourceDirEntry);
4734 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4737 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4738 g_error ("WriteFile returned %d\n", GetLastError ());
4742 * mono_image_create_pefile:
4743 * @mb: a module builder object
4745 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4746 * assembly->pefile where it can be easily retrieved later in chunks.
4749 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4750 MonoMSDOSHeader *msdos;
4751 MonoDotNetHeader *header;
4752 MonoSectionTable *section;
4753 MonoCLIHeader *cli_header;
4754 guint32 size, image_size, virtual_base, text_offset;
4755 guint32 header_start, section_start, file_offset, virtual_offset;
4756 MonoDynamicImage *assembly;
4757 MonoReflectionAssemblyBuilder *assemblyb;
4758 MonoDynamicStream pefile_stream = {0};
4759 MonoDynamicStream *pefile = &pefile_stream;
4761 guint32 *rva, value;
4763 static const unsigned char msheader[] = {
4764 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4765 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4767 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4768 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4769 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4770 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4771 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4774 assemblyb = mb->assemblyb;
4776 mono_image_basic_init (assemblyb);
4777 assembly = mb->dynamic_image;
4779 assembly->pe_kind = assemblyb->pe_kind;
4780 assembly->machine = assemblyb->machine;
4781 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4782 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4784 mono_image_build_metadata (mb);
4786 if (mb->is_main && assemblyb->resources) {
4787 int len = mono_array_length (assemblyb->resources);
4788 for (i = 0; i < len; ++i)
4789 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4792 if (mb->resources) {
4793 int len = mono_array_length (mb->resources);
4794 for (i = 0; i < len; ++i)
4795 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4798 build_compressed_metadata (assembly);
4801 assembly_add_win32_resources (assembly, assemblyb);
4803 nsections = calc_section_size (assembly);
4805 /* The DOS header and stub */
4806 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4807 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
4809 /* the dotnet header */
4810 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4812 /* the section tables */
4813 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4815 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4816 virtual_offset = VIRT_ALIGN;
4819 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4820 if (!assembly->sections [i].size)
4823 file_offset += FILE_ALIGN - 1;
4824 file_offset &= ~(FILE_ALIGN - 1);
4825 virtual_offset += VIRT_ALIGN - 1;
4826 virtual_offset &= ~(VIRT_ALIGN - 1);
4828 assembly->sections [i].offset = file_offset;
4829 assembly->sections [i].rva = virtual_offset;
4831 file_offset += assembly->sections [i].size;
4832 virtual_offset += assembly->sections [i].size;
4833 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4836 file_offset += FILE_ALIGN - 1;
4837 file_offset &= ~(FILE_ALIGN - 1);
4839 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4841 /* back-patch info */
4842 msdos = (MonoMSDOSHeader*)pefile->data;
4843 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4845 header = (MonoDotNetHeader*)(pefile->data + header_start);
4846 header->pesig [0] = 'P';
4847 header->pesig [1] = 'E';
4849 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4850 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4851 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4852 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4853 if (assemblyb->pekind == 1) {
4855 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4858 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4861 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4863 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4864 header->pe.pe_major = 6;
4865 header->pe.pe_minor = 0;
4866 size = assembly->sections [MONO_SECTION_TEXT].size;
4867 size += FILE_ALIGN - 1;
4868 size &= ~(FILE_ALIGN - 1);
4869 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4870 size = assembly->sections [MONO_SECTION_RSRC].size;
4871 size += FILE_ALIGN - 1;
4872 size &= ~(FILE_ALIGN - 1);
4873 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4874 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4875 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4876 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4877 /* pe_rva_entry_point always at the beginning of the text section */
4878 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4880 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4881 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4882 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4883 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4884 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4885 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4886 size = section_start;
4887 size += FILE_ALIGN - 1;
4888 size &= ~(FILE_ALIGN - 1);
4889 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4891 size += VIRT_ALIGN - 1;
4892 size &= ~(VIRT_ALIGN - 1);
4893 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4896 // Translate the PEFileKind value to the value expected by the Windows loader
4902 // PEFileKinds.Dll == 1
4903 // PEFileKinds.ConsoleApplication == 2
4904 // PEFileKinds.WindowApplication == 3
4907 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4908 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4910 if (assemblyb->pekind == 3)
4915 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4917 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4918 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4919 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4920 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4921 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4922 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4924 /* fill data directory entries */
4926 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4927 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4929 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4930 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4932 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4933 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4934 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4935 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4936 /* patch entrypoint name */
4937 if (assemblyb->pekind == 1)
4938 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4940 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4941 /* patch imported function RVA name */
4942 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4943 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4945 /* the import table */
4946 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4947 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4948 /* patch imported dll RVA name and other entries in the dir */
4949 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4950 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4951 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4952 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4953 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4954 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4956 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
4957 value = (assembly->text_rva + assembly->imp_names_offset);
4958 *p++ = (value) & 0xff;
4959 *p++ = (value >> 8) & (0xff);
4960 *p++ = (value >> 16) & (0xff);
4961 *p++ = (value >> 24) & (0xff);
4963 /* the CLI header info */
4964 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4965 cli_header->ch_size = GUINT32_FROM_LE (72);
4966 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4967 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4968 if (assemblyb->entry_point) {
4969 guint32 table_idx = 0;
4970 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4971 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4972 table_idx = methodb->table_idx;
4974 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4976 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4978 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4980 /* The embedded managed resources */
4981 text_offset = assembly->text_rva + assembly->code.index;
4982 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4983 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4984 text_offset += assembly->resources.index;
4985 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4986 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4987 text_offset += assembly->meta_size;
4988 if (assembly->strong_name_size) {
4989 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4990 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4991 text_offset += assembly->strong_name_size;
4994 /* write the section tables and section content */
4995 section = (MonoSectionTable*)(pefile->data + section_start);
4996 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4997 static const char section_names [][7] = {
4998 ".text", ".rsrc", ".reloc"
5000 if (!assembly->sections [i].size)
5002 strcpy (section->st_name, section_names [i]);
5003 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5004 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5005 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5006 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5007 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5008 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5009 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5013 checked_write_file (file, pefile->data, pefile->index);
5015 mono_dynamic_stream_reset (pefile);
5017 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5018 if (!assembly->sections [i].size)
5021 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5022 g_error ("SetFilePointer returned %d\n", GetLastError ());
5025 case MONO_SECTION_TEXT:
5026 /* patch entry point */
5027 p = (guchar*)(assembly->code.data + 2);
5028 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5029 *p++ = (value) & 0xff;
5030 *p++ = (value >> 8) & 0xff;
5031 *p++ = (value >> 16) & 0xff;
5032 *p++ = (value >> 24) & 0xff;
5034 checked_write_file (file, assembly->code.data, assembly->code.index);
5035 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5036 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5037 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5040 g_free (assembly->image.raw_metadata);
5042 case MONO_SECTION_RELOC: {
5046 guint16 type_and_offset;
5050 g_assert (sizeof (reloc) == 12);
5052 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5053 reloc.block_size = GUINT32_FROM_LE (12);
5056 * the entrypoint is always at the start of the text section
5057 * 3 is IMAGE_REL_BASED_HIGHLOW
5058 * 2 is patch_size_rva - text_rva
5060 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5063 checked_write_file (file, &reloc, sizeof (reloc));
5067 case MONO_SECTION_RSRC:
5068 if (assembly->win32_res) {
5070 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5071 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5072 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5076 g_assert_not_reached ();
5080 /* check that the file is properly padded */
5081 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5082 g_error ("SetFilePointer returned %d\n", GetLastError ());
5083 if (! SetEndOfFile (file))
5084 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5086 mono_dynamic_stream_reset (&assembly->code);
5087 mono_dynamic_stream_reset (&assembly->us);
5088 mono_dynamic_stream_reset (&assembly->blob);
5089 mono_dynamic_stream_reset (&assembly->guid);
5090 mono_dynamic_stream_reset (&assembly->sheap);
5092 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5093 g_hash_table_destroy (assembly->blob_cache);
5094 assembly->blob_cache = NULL;
5097 MonoReflectionModule *
5098 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5102 MonoImageOpenStatus status;
5103 MonoDynamicAssembly *assembly;
5104 guint32 module_count;
5105 MonoImage **new_modules;
5106 gboolean *new_modules_loaded;
5108 name = mono_string_to_utf8 (fileName);
5110 image = mono_image_open (name, &status);
5113 if (status == MONO_IMAGE_ERROR_ERRNO)
5114 exc = mono_get_exception_file_not_found (fileName);
5116 exc = mono_get_exception_bad_image_format (name);
5118 mono_raise_exception (exc);
5123 assembly = ab->dynamic_assembly;
5124 image->assembly = (MonoAssembly*)assembly;
5126 module_count = image->assembly->image->module_count;
5127 new_modules = g_new0 (MonoImage *, module_count + 1);
5128 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5130 if (image->assembly->image->modules)
5131 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5132 if (image->assembly->image->modules_loaded)
5133 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5134 new_modules [module_count] = image;
5135 new_modules_loaded [module_count] = TRUE;
5136 mono_image_addref (image);
5138 g_free (image->assembly->image->modules);
5139 image->assembly->image->modules = new_modules;
5140 image->assembly->image->modules_loaded = new_modules_loaded;
5141 image->assembly->image->module_count ++;
5143 mono_assembly_load_references (image, &status);
5145 mono_image_close (image);
5146 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5149 return mono_module_get_object (mono_domain_get (), image);
5153 * We need to return always the same object for MethodInfo, FieldInfo etc..
5154 * but we need to consider the reflected type.
5155 * type uses a different hash, since it uses custom hash/equal functions.
5160 MonoClass *refclass;
5164 reflected_equal (gconstpointer a, gconstpointer b) {
5165 const ReflectedEntry *ea = a;
5166 const ReflectedEntry *eb = b;
5168 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5172 reflected_hash (gconstpointer a) {
5173 const ReflectedEntry *ea = a;
5174 return mono_aligned_addr_hash (ea->item);
5177 #define CHECK_OBJECT(t,p,k) \
5183 mono_domain_lock (domain); \
5184 if (!domain->refobject_hash) \
5185 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5186 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5187 mono_domain_unlock (domain); \
5190 mono_domain_unlock (domain); \
5193 #ifndef HAVE_NULL_GC
5194 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5196 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5199 #define CACHE_OBJECT(t,p,o,k) \
5202 ReflectedEntry pe; \
5204 pe.refclass = (k); \
5205 mono_domain_lock (domain); \
5206 if (!domain->refobject_hash) \
5207 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5208 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5210 ReflectedEntry *e = ALLOC_REFENTRY; \
5212 e->refclass = (k); \
5213 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5216 mono_domain_unlock (domain); \
5221 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5223 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5227 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5229 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5233 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5235 MonoDynamicImage *image = moduleb->dynamic_image;
5236 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5239 MonoImage **new_modules;
5242 * FIXME: we already created an image in mono_image_basic_init (), but
5243 * we don't know which module it belongs to, since that is only
5244 * determined at assembly save time.
5246 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5247 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5249 moduleb->module.image = &image->image;
5250 moduleb->dynamic_image = image;
5251 register_module (mono_object_domain (moduleb), moduleb, image);
5253 /* register the module with the assembly */
5254 ass = ab->dynamic_assembly->assembly.image;
5255 module_count = ass->module_count;
5256 new_modules = g_new0 (MonoImage *, module_count + 1);
5259 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5260 new_modules [module_count] = &image->image;
5261 mono_image_addref (&image->image);
5263 g_free (ass->modules);
5264 ass->modules = new_modules;
5265 ass->module_count ++;
5270 * mono_assembly_get_object:
5271 * @domain: an app domain
5272 * @assembly: an assembly
5274 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5276 MonoReflectionAssembly*
5277 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5279 static MonoClass *System_Reflection_Assembly;
5280 MonoReflectionAssembly *res;
5282 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5283 if (!System_Reflection_Assembly)
5284 System_Reflection_Assembly = mono_class_from_name (
5285 mono_defaults.corlib, "System.Reflection", "Assembly");
5286 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5287 res->assembly = assembly;
5289 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5294 MonoReflectionModule*
5295 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5297 static MonoClass *System_Reflection_Module;
5298 MonoReflectionModule *res;
5301 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5302 if (!System_Reflection_Module)
5303 System_Reflection_Module = mono_class_from_name (
5304 mono_defaults.corlib, "System.Reflection", "Module");
5305 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5308 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5310 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5311 basename = g_path_get_basename (image->name);
5312 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5313 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5317 if (image->assembly->image == image) {
5318 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5322 if (image->assembly->image->modules) {
5323 for (i = 0; i < image->assembly->image->module_count; i++) {
5324 if (image->assembly->image->modules [i] == image)
5325 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5327 g_assert (res->token);
5331 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5334 MonoReflectionModule*
5335 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5337 static MonoClass *System_Reflection_Module;
5338 MonoReflectionModule *res;
5339 MonoTableInfo *table;
5340 guint32 cols [MONO_FILE_SIZE];
5342 guint32 i, name_idx;
5345 if (!System_Reflection_Module)
5346 System_Reflection_Module = mono_class_from_name (
5347 mono_defaults.corlib, "System.Reflection", "Module");
5348 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5350 table = &image->tables [MONO_TABLE_FILE];
5351 g_assert (table_index < table->rows);
5352 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5355 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5356 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5358 /* Check whenever the row has a corresponding row in the moduleref table */
5359 table = &image->tables [MONO_TABLE_MODULEREF];
5360 for (i = 0; i < table->rows; ++i) {
5361 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5362 val = mono_metadata_string_heap (image, name_idx);
5363 if (strcmp (val, name) == 0)
5364 res->image = image->modules [i];
5367 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5368 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5369 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5370 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5371 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5377 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5379 if ((t1->type != t2->type) ||
5380 (t1->byref != t2->byref))
5384 case MONO_TYPE_VOID:
5385 case MONO_TYPE_BOOLEAN:
5386 case MONO_TYPE_CHAR:
5397 case MONO_TYPE_STRING:
5400 case MONO_TYPE_OBJECT:
5401 case MONO_TYPE_TYPEDBYREF:
5403 case MONO_TYPE_VALUETYPE:
5404 case MONO_TYPE_CLASS:
5405 case MONO_TYPE_SZARRAY:
5406 return t1->data.klass == t2->data.klass;
5408 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5409 case MONO_TYPE_ARRAY:
5410 if (t1->data.array->rank != t2->data.array->rank)
5412 return t1->data.array->eklass == t2->data.array->eklass;
5413 case MONO_TYPE_GENERICINST: {
5415 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5416 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5417 if (i1->type_argc != i2->type_argc)
5419 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5420 &t2->data.generic_class->container_class->byval_arg))
5422 /* FIXME: we should probably just compare the instance pointers directly. */
5423 for (i = 0; i < i1->type_argc; ++i) {
5424 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5430 case MONO_TYPE_MVAR:
5431 return t1->data.generic_param == t2->data.generic_param;
5433 g_error ("implement type compare for %0x!", t1->type);
5441 mymono_metadata_type_hash (MonoType *t1)
5447 hash |= t1->byref << 6; /* do not collide with t1->type values */
5449 case MONO_TYPE_VALUETYPE:
5450 case MONO_TYPE_CLASS:
5451 case MONO_TYPE_SZARRAY:
5452 /* check if the distribution is good enough */
5453 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5455 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5456 case MONO_TYPE_GENERICINST: {
5458 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5459 hash += g_str_hash (t1->data.generic_class->container_class->name);
5461 for (i = 0; i < inst->type_argc; ++i) {
5462 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5471 static MonoReflectionGenericClass*
5472 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5474 static MonoClass *System_Reflection_MonoGenericClass;
5475 MonoReflectionGenericClass *res;
5476 MonoClass *klass, *gklass;
5478 if (!System_Reflection_MonoGenericClass) {
5479 System_Reflection_MonoGenericClass = mono_class_from_name (
5480 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5481 g_assert (System_Reflection_MonoGenericClass);
5484 klass = mono_class_from_mono_type (geninst);
5485 gklass = klass->generic_class->container_class;
5487 mono_class_init (klass);
5490 /* FIXME: allow unpinned later */
5491 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5493 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5496 res->type.type = geninst;
5497 g_assert (gklass->reflection_info);
5498 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
5499 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5505 verify_safe_for_managed_space (MonoType *type)
5507 switch (type->type) {
5509 case MONO_TYPE_ARRAY:
5510 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5512 return verify_safe_for_managed_space (type->data.type);
5513 case MONO_TYPE_SZARRAY:
5514 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5515 case MONO_TYPE_GENERICINST: {
5516 MonoGenericInst *inst = type->data.generic_class->inst;
5520 for (i = 0; i < inst->type_argc; ++i)
5521 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5527 case MONO_TYPE_MVAR:
5534 * mono_type_get_object:
5535 * @domain: an app domain
5538 * Return an System.MonoType object representing the type @type.
5541 mono_type_get_object (MonoDomain *domain, MonoType *type)
5543 MonoReflectionType *res;
5544 MonoClass *klass = mono_class_from_mono_type (type);
5546 mono_domain_lock (domain);
5547 if (!domain->type_hash)
5548 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5549 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5550 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5551 mono_domain_unlock (domain);
5554 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
5555 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
5556 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5557 mono_g_hash_table_insert (domain->type_hash, type, res);
5558 mono_domain_unlock (domain);
5562 if (!verify_safe_for_managed_space (type)) {
5563 mono_domain_unlock (domain);
5564 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5567 if (klass->reflection_info && !klass->wastypebuilder) {
5568 /* g_assert_not_reached (); */
5569 /* should this be considered an error condition? */
5571 mono_domain_unlock (domain);
5572 return klass->reflection_info;
5575 mono_class_init (klass);
5577 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5579 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5582 mono_g_hash_table_insert (domain->type_hash, type, res);
5583 mono_domain_unlock (domain);
5588 * mono_method_get_object:
5589 * @domain: an app domain
5591 * @refclass: the reflected type (can be NULL)
5593 * Return an System.Reflection.MonoMethod object representing the method @method.
5595 MonoReflectionMethod*
5596 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5599 * We use the same C representation for methods and constructors, but the type
5600 * name in C# is different.
5602 static MonoClass *System_Reflection_MonoMethod = NULL;
5603 static MonoClass *System_Reflection_MonoCMethod = NULL;
5604 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5605 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5607 MonoReflectionMethod *ret;
5609 if (method->is_inflated) {
5610 MonoReflectionGenericMethod *gret;
5612 refclass = method->klass;
5613 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5614 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5615 if (!System_Reflection_MonoGenericCMethod)
5616 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5617 klass = System_Reflection_MonoGenericCMethod;
5619 if (!System_Reflection_MonoGenericMethod)
5620 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5621 klass = System_Reflection_MonoGenericMethod;
5623 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5624 gret->method.method = method;
5625 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5626 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5627 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5631 refclass = method->klass;
5633 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5634 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5635 if (!System_Reflection_MonoCMethod)
5636 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5637 klass = System_Reflection_MonoCMethod;
5640 if (!System_Reflection_MonoMethod)
5641 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5642 klass = System_Reflection_MonoMethod;
5644 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5645 ret->method = method;
5646 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5647 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5651 * mono_field_get_object:
5652 * @domain: an app domain
5656 * Return an System.Reflection.MonoField object representing the field @field
5659 MonoReflectionField*
5660 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5662 MonoReflectionField *res;
5663 static MonoClass *monofield_klass;
5665 CHECK_OBJECT (MonoReflectionField *, field, klass);
5666 if (!monofield_klass)
5667 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5668 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
5671 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5672 if (field->generic_info)
5673 res->attrs = field->generic_info->generic_type->attrs;
5675 res->attrs = field->type->attrs;
5676 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5677 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5681 * mono_property_get_object:
5682 * @domain: an app domain
5684 * @property: a property
5686 * Return an System.Reflection.MonoProperty object representing the property @property
5689 MonoReflectionProperty*
5690 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5692 MonoReflectionProperty *res;
5693 static MonoClass *monoproperty_klass;
5695 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5696 if (!monoproperty_klass)
5697 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5698 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
5700 res->property = property;
5701 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5705 * mono_event_get_object:
5706 * @domain: an app domain
5710 * Return an System.Reflection.MonoEvent object representing the event @event
5713 MonoReflectionEvent*
5714 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5716 MonoReflectionEvent *res;
5717 static MonoClass *monoevent_klass;
5719 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5720 if (!monoevent_klass)
5721 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5722 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
5725 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5729 * mono_get_reflection_missing_object:
5730 * @domain: Domain where the object lives
5732 * Returns the System.Reflection.Missing.Value singleton object
5733 * (of type System.Reflection.Missing).
5735 * Used as the value for ParameterInfo.DefaultValue when Optional
5739 mono_get_reflection_missing_object (MonoDomain *domain)
5742 static MonoClassField *missing_value_field = NULL;
5744 if (!missing_value_field) {
5745 MonoClass *missing_klass;
5746 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
5747 mono_class_init (missing_klass);
5748 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
5749 g_assert (missing_value_field);
5751 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
5757 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
5760 *dbnull = mono_get_dbnull_object (domain);
5765 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
5767 if (!*reflection_missing)
5768 *reflection_missing = mono_get_reflection_missing_object (domain);
5769 return *reflection_missing;
5773 * mono_param_get_objects:
5774 * @domain: an app domain
5777 * Return an System.Reflection.ParameterInfo array object representing the parameters
5778 * in the method @method.
5781 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5783 static MonoClass *System_Reflection_ParameterInfo;
5784 MonoArray *res = NULL;
5785 MonoReflectionMethod *member = NULL;
5786 MonoReflectionParameter *param = NULL;
5787 char **names, **blobs = NULL;
5788 guint32 *types = NULL;
5789 MonoType *type = NULL;
5790 MonoObject *dbnull = NULL;
5791 MonoObject *missing = NULL;
5792 MonoMarshalSpec **mspecs;
5793 MonoMethodSignature *sig;
5796 if (!System_Reflection_ParameterInfo)
5797 System_Reflection_ParameterInfo = mono_class_from_name (
5798 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5800 if (!mono_method_signature (method)->param_count)
5801 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5803 /* Note: the cache is based on the address of the signature into the method
5804 * since we already cache MethodInfos with the method as keys.
5806 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5808 sig = mono_method_signature (method);
5809 member = mono_method_get_object (domain, method, NULL);
5810 names = g_new (char *, sig->param_count);
5811 mono_method_get_param_names (method, (const char **) names);
5813 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5814 mono_method_get_marshal_info (method, mspecs);
5816 res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5817 for (i = 0; i < sig->param_count; ++i) {
5818 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5819 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5820 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5821 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5822 param->PositionImpl = i;
5823 param->AttrsImpl = sig->params [i]->attrs;
5825 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5826 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
5827 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
5829 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
5833 blobs = g_new0 (char *, sig->param_count);
5834 types = g_new0 (guint32, sig->param_count);
5835 get_default_param_value_blobs (method, blobs, types);
5838 /* Build MonoType for the type from the Constant Table */
5840 type = g_new0 (MonoType, 1);
5841 type->type = types [i];
5842 type->data.klass = NULL;
5843 if (types [i] == MONO_TYPE_CLASS)
5844 type->data.klass = mono_defaults.object_class;
5845 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5846 /* For enums, types [i] contains the base type */
5848 type->type = MONO_TYPE_VALUETYPE;
5849 type->data.klass = mono_class_from_mono_type (sig->params [i]);
5851 type->data.klass = mono_class_from_mono_type (type);
5853 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5855 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5856 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
5857 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
5858 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
5860 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
5866 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5868 mono_array_setref (res, i, param);
5875 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5877 mono_metadata_free_marshal_spec (mspecs [i]);
5880 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5884 * mono_method_body_get_object:
5885 * @domain: an app domain
5888 * Return an System.Reflection.MethodBody object representing the method @method.
5890 MonoReflectionMethodBody*
5891 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5893 static MonoClass *System_Reflection_MethodBody = NULL;
5894 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5895 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5896 MonoReflectionMethodBody *ret;
5897 MonoMethodNormal *mn;
5898 MonoMethodHeader *header;
5899 guint32 method_rva, local_var_sig_token;
5901 unsigned char format, flags;
5904 if (!System_Reflection_MethodBody)
5905 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5906 if (!System_Reflection_LocalVariableInfo)
5907 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5908 if (!System_Reflection_ExceptionHandlingClause)
5909 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5911 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5913 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5914 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5915 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5916 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5918 mn = (MonoMethodNormal *)method;
5919 header = mono_method_get_header (method);
5921 /* Obtain local vars signature token */
5922 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5923 ptr = mono_image_rva_map (method->klass->image, method_rva);
5924 flags = *(const unsigned char *) ptr;
5925 format = flags & METHOD_HEADER_FORMAT_MASK;
5927 case METHOD_HEADER_TINY_FORMAT:
5928 case METHOD_HEADER_TINY_FORMAT1:
5929 local_var_sig_token = 0;
5931 case METHOD_HEADER_FAT_FORMAT:
5935 local_var_sig_token = read32 (ptr);
5938 g_assert_not_reached ();
5941 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5943 ret->init_locals = header->init_locals;
5944 ret->max_stack = header->max_stack;
5945 ret->local_var_sig_token = local_var_sig_token;
5946 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5947 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5950 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5951 for (i = 0; i < header->num_locals; ++i) {
5952 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5953 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5954 info->is_pinned = header->locals [i]->pinned;
5955 info->local_index = i;
5956 mono_array_setref (ret->locals, i, info);
5960 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5961 for (i = 0; i < header->num_clauses; ++i) {
5962 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5963 MonoExceptionClause *clause = &header->clauses [i];
5965 info->flags = clause->flags;
5966 info->try_offset = clause->try_offset;
5967 info->try_length = clause->try_len;
5968 info->handler_offset = clause->handler_offset;
5969 info->handler_length = clause->handler_len;
5970 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5971 info->filter_offset = clause->data.filter_offset;
5972 else if (clause->data.catch_class)
5973 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5975 mono_array_setref (ret->clauses, i, info);
5978 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5983 * mono_get_dbnull_object:
5984 * @domain: Domain where the object lives
5986 * Returns the System.DBNull.Value singleton object
5988 * Used as the value for ParameterInfo.DefaultValue
5991 mono_get_dbnull_object (MonoDomain *domain)
5994 static MonoClassField *dbnull_value_field = NULL;
5996 if (!dbnull_value_field) {
5997 MonoClass *dbnull_klass;
5998 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5999 mono_class_init (dbnull_klass);
6000 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6001 g_assert (dbnull_value_field);
6003 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6009 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6011 guint32 param_index, i, lastp, crow = 0;
6012 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6015 MonoClass *klass = method->klass;
6016 MonoImage *image = klass->image;
6017 MonoMethodSignature *methodsig = mono_method_signature (method);
6019 MonoTableInfo *constt;
6020 MonoTableInfo *methodt;
6021 MonoTableInfo *paramt;
6023 if (!methodsig->param_count)
6026 mono_class_init (klass);
6028 if (klass->image->dynamic) {
6029 MonoReflectionMethodAux *aux;
6030 if (method->is_inflated)
6031 method = ((MonoMethodInflated*)method)->declaring;
6032 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6033 if (aux && aux->param_defaults) {
6034 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6035 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6040 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6041 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6042 constt = &image->tables [MONO_TABLE_CONSTANT];
6044 idx = mono_method_get_index (method) - 1;
6045 g_assert (idx != -1);
6047 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6048 if (idx + 1 < methodt->rows)
6049 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6051 lastp = paramt->rows + 1;
6053 for (i = param_index; i < lastp; ++i) {
6056 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6057 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6059 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6062 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6067 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6068 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6069 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6076 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6081 MonoType *basetype = type;
6086 klass = mono_class_from_mono_type (type);
6087 if (klass->valuetype) {
6088 object = mono_object_new (domain, klass);
6089 retval = ((gchar *) object + sizeof (MonoObject));
6090 if (klass->enumtype)
6091 basetype = klass->enum_basetype;
6096 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6103 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6107 memset (assembly, 0, sizeof (MonoAssemblyName));
6109 assembly->culture = "";
6110 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6112 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6115 while (g_ascii_isspace (*p) || *p == ',') {
6124 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6126 assembly->major = strtoul (p, &s, 10);
6127 if (s == p || *s != '.')
6130 assembly->minor = strtoul (p, &s, 10);
6131 if (s == p || *s != '.')
6134 assembly->build = strtoul (p, &s, 10);
6135 if (s == p || *s != '.')
6138 assembly->revision = strtoul (p, &s, 10);
6142 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6144 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6145 assembly->culture = "";
6148 assembly->culture = p;
6149 while (*p && *p != ',') {
6153 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6155 if (strncmp (p, "null", 4) == 0) {
6160 while (*p && *p != ',') {
6163 len = (p - start + 1);
6164 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6165 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6166 g_strlcpy ((char*)assembly->public_key_token, start, len);
6169 while (*p && *p != ',')
6173 while (g_ascii_isspace (*p) || *p == ',') {
6187 * mono_reflection_parse_type:
6190 * Parse a type name as accepted by the GetType () method and output the info
6191 * extracted in the info structure.
6192 * the name param will be mangled, so, make a copy before passing it to this function.
6193 * The fields in info will be valid until the memory pointed to by name is valid.
6195 * See also mono_type_get_name () below.
6197 * Returns: 0 on parse error.
6200 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6201 MonoTypeNameParse *info)
6203 char *start, *p, *w, *temp, *last_point, *startn;
6204 int in_modifiers = 0;
6205 int isbyref = 0, rank, arity = 0, i;
6207 start = p = w = name;
6209 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6210 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6211 info->name = info->name_space = NULL;
6212 info->nested = NULL;
6213 info->modifiers = NULL;
6214 info->type_arguments = NULL;
6216 /* last_point separates the namespace from the name */
6222 *p = 0; /* NULL terminate the name */
6224 info->nested = g_list_append (info->nested, startn);
6225 /* we have parsed the nesting namespace + name */
6229 info->name_space = start;
6231 info->name = last_point + 1;
6233 info->name_space = (char *)"";
6252 i = strtol (p, &temp, 10);
6269 info->name_space = start;
6271 info->name = last_point + 1;
6273 info->name_space = (char *)"";
6280 if (isbyref) /* only one level allowed by the spec */
6283 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6287 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6293 info->type_arguments = g_ptr_array_new ();
6294 for (i = 0; i < arity; i++) {
6295 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6296 gboolean fqname = FALSE;
6298 g_ptr_array_add (info->type_arguments, subinfo);
6305 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6316 while (*p && (*p != ']'))
6324 if (g_ascii_isspace (*aname)) {
6331 !assembly_name_to_aname (&subinfo->assembly, aname))
6335 if (i + 1 < arity) {
6355 else if (*p != '*') /* '*' means unknown lower bound */
6361 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6372 if (g_ascii_isspace (*p)) {
6379 return 0; /* missing assembly name */
6380 if (!assembly_name_to_aname (&info->assembly, p))
6386 if (info->assembly.name)
6389 // *w = 0; /* terminate class name */
6391 if (!info->name || !*info->name)
6395 /* add other consistency checks */
6400 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6402 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6406 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6408 gboolean type_resolve = FALSE;
6410 MonoImage *rootimage = image;
6412 if (info->assembly.name) {
6413 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6415 /* then we must load the assembly ourselve - see #60439 */
6416 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6420 image = assembly->image;
6421 } else if (!image) {
6422 image = mono_defaults.corlib;
6425 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6426 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6427 image = mono_defaults.corlib;
6428 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6435 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6442 image = mono_defaults.corlib;
6445 klass = mono_class_from_name_case (image, info->name_space, info->name);
6447 klass = mono_class_from_name (image, info->name_space, info->name);
6450 for (mod = info->nested; mod; mod = mod->next) {
6453 mono_class_init (klass);
6454 nested = klass->nested_classes;
6457 klass = nested->data;
6459 if (g_strcasecmp (klass->name, mod->data) == 0)
6462 if (strcmp (klass->name, mod->data) == 0)
6466 nested = nested->next;
6473 mono_class_init (klass);
6475 if (info->type_arguments) {
6476 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6477 MonoReflectionType *the_type;
6481 for (i = 0; i < info->type_arguments->len; i++) {
6482 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6484 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
6485 if (!type_args [i]) {
6491 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6493 instance = mono_reflection_bind_generic_parameters (
6494 the_type, info->type_arguments->len, type_args);
6500 klass = mono_class_from_mono_type (instance);
6503 for (mod = info->modifiers; mod; mod = mod->next) {
6504 modval = GPOINTER_TO_UINT (mod->data);
6505 if (!modval) { /* byref: must be last modifier */
6506 return &klass->this_arg;
6507 } else if (modval == -1) {
6508 klass = mono_ptr_class_get (&klass->byval_arg);
6509 } else { /* array rank */
6510 klass = mono_array_class_get (klass, modval);
6512 mono_class_init (klass);
6515 return &klass->byval_arg;
6519 * mono_reflection_get_type:
6520 * @image: a metadata context
6521 * @info: type description structure
6522 * @ignorecase: flag for case-insensitive string compares
6523 * @type_resolve: whenever type resolve was already tried
6525 * Build a MonoType from the type description in @info.
6530 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
6531 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
6535 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
6537 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
6541 g_assert (assembly->dynamic);
6543 /* Enumerate all modules */
6546 if (abuilder->modules) {
6547 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6548 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6549 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
6555 if (!type && abuilder->loaded_modules) {
6556 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6557 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6558 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
6568 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6571 MonoReflectionAssembly *assembly;
6575 if (image && image->dynamic)
6576 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
6578 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
6581 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6588 *type_resolve = TRUE;
6591 /* Reconstruct the type name */
6592 fullName = g_string_new ("");
6593 if (info->name_space && (info->name_space [0] != '\0'))
6594 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6596 g_string_printf (fullName, info->name);
6597 for (mod = info->nested; mod; mod = mod->next)
6598 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6600 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6602 if (assembly->assembly->dynamic)
6603 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
6605 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
6608 g_string_free (fullName, TRUE);
6613 mono_reflection_free_type_info (MonoTypeNameParse *info)
6615 g_list_free (info->modifiers);
6616 g_list_free (info->nested);
6618 if (info->type_arguments) {
6621 for (i = 0; i < info->type_arguments->len; i++) {
6622 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6624 mono_reflection_free_type_info (subinfo);
6625 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
6629 g_ptr_array_free (info->type_arguments, TRUE);
6634 * mono_reflection_type_from_name:
6636 * @image: a metadata context (can be NULL).
6638 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6639 * it defaults to get the type from @image or, if @image is NULL or loading
6640 * from it fails, uses corlib.
6644 mono_reflection_type_from_name (char *name, MonoImage *image)
6646 MonoType *type = NULL;
6647 MonoTypeNameParse info;
6650 /* Make a copy since parse_type modifies its argument */
6651 tmp = g_strdup (name);
6653 /*g_print ("requested type %s\n", str);*/
6654 if (mono_reflection_parse_type (tmp, &info)) {
6655 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6659 mono_reflection_free_type_info (&info);
6664 * mono_reflection_get_token:
6666 * Return the metadata token of OBJ which should be an object
6667 * representing a metadata element.
6670 mono_reflection_get_token (MonoObject *obj)
6675 klass = obj->vtable->klass;
6677 if (strcmp (klass->name, "MethodBuilder") == 0) {
6678 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6680 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6681 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6682 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6684 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6685 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6686 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6688 /* Call mono_image_create_token so the object gets added to the tokens hash table */
6689 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE);
6690 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6691 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6692 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6693 } else if (strcmp (klass->name, "MonoType") == 0) {
6694 MonoReflectionType *tb = (MonoReflectionType *)obj;
6695 token = mono_class_from_mono_type (tb->type)->type_token;
6696 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6697 strcmp (klass->name, "MonoMethod") == 0 ||
6698 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6699 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6700 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6701 if (m->method->is_inflated) {
6702 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6703 return inflated->declaring->token;
6705 token = m->method->token;
6707 } else if (strcmp (klass->name, "MonoField") == 0) {
6708 MonoReflectionField *f = (MonoReflectionField*)obj;
6710 if (f->field->generic_info && f->field->generic_info->reflection_info)
6711 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6713 token = mono_class_get_field_token (f->field);
6714 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6715 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6717 token = mono_class_get_property_token (p->property);
6718 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6719 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6721 token = mono_class_get_event_token (p->event);
6722 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6723 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6725 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6726 } else if (strcmp (klass->name, "Module") == 0) {
6727 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6730 } else if (strcmp (klass->name, "Assembly") == 0) {
6731 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6733 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6734 MonoException *ex = mono_get_exception_not_implemented (msg);
6736 mono_raise_exception (ex);
6743 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6745 int slen, type = t->type;
6746 MonoClass *tklass = t->data.klass;
6752 case MONO_TYPE_BOOLEAN: {
6753 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6758 case MONO_TYPE_CHAR:
6760 case MONO_TYPE_I2: {
6761 guint16 *val = g_malloc (sizeof (guint16));
6766 #if SIZEOF_VOID_P == 4
6772 case MONO_TYPE_I4: {
6773 guint32 *val = g_malloc (sizeof (guint32));
6778 #if SIZEOF_VOID_P == 8
6779 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6783 case MONO_TYPE_I8: {
6784 guint64 *val = g_malloc (sizeof (guint64));
6789 case MONO_TYPE_R8: {
6790 double *val = g_malloc (sizeof (double));
6795 case MONO_TYPE_VALUETYPE:
6796 if (t->data.klass->enumtype) {
6797 type = t->data.klass->enum_basetype->type;
6800 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6803 case MONO_TYPE_STRING:
6804 if (*p == (char)0xFF) {
6808 slen = mono_metadata_decode_value (p, &p);
6810 return mono_string_new_len (mono_domain_get (), p, slen);
6811 case MONO_TYPE_CLASS: {
6814 if (*p == (char)0xFF) {
6819 slen = mono_metadata_decode_value (p, &p);
6820 n = g_memdup (p, slen + 1);
6822 t = mono_reflection_type_from_name (n, image);
6824 g_warning ("Cannot load type '%s'", n);
6828 return mono_type_get_object (mono_domain_get (), t);
6832 case MONO_TYPE_OBJECT: {
6835 MonoClass *subc = NULL;
6840 } else if (subt == 0x0E) {
6841 type = MONO_TYPE_STRING;
6843 } else if (subt == 0x1D) {
6844 MonoType simple_type = {{0}};
6849 /* See Partition II, Appendix B3 */
6850 etype = MONO_TYPE_OBJECT;
6851 type = MONO_TYPE_SZARRAY;
6852 simple_type.type = etype;
6853 tklass = mono_class_from_mono_type (&simple_type);
6855 } else if (subt == 0x55) {
6858 slen = mono_metadata_decode_value (p, &p);
6859 n = g_memdup (p, slen + 1);
6861 t = mono_reflection_type_from_name (n, image);
6863 g_error ("Cannot load type '%s'", n);
6866 subc = mono_class_from_mono_type (t);
6867 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6868 MonoType simple_type = {{0}};
6869 simple_type.type = subt;
6870 subc = mono_class_from_mono_type (&simple_type);
6872 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6874 val = load_cattr_value (image, &subc->byval_arg, p, end);
6875 obj = mono_object_new (mono_domain_get (), subc);
6876 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6880 case MONO_TYPE_SZARRAY: {
6882 guint32 i, alen, basetype;
6885 if (alen == 0xffffffff) {
6889 arr = mono_array_new (mono_domain_get(), tklass, alen);
6890 basetype = tklass->byval_arg.type;
6891 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
6892 basetype = tklass->enum_basetype->type;
6897 case MONO_TYPE_BOOLEAN:
6898 for (i = 0; i < alen; i++) {
6899 MonoBoolean val = *p++;
6900 mono_array_set (arr, MonoBoolean, i, val);
6903 case MONO_TYPE_CHAR:
6906 for (i = 0; i < alen; i++) {
6907 guint16 val = read16 (p);
6908 mono_array_set (arr, guint16, i, val);
6915 for (i = 0; i < alen; i++) {
6916 guint32 val = read32 (p);
6917 mono_array_set (arr, guint32, i, val);
6922 for (i = 0; i < alen; i++) {
6925 mono_array_set (arr, double, i, val);
6931 for (i = 0; i < alen; i++) {
6932 guint64 val = read64 (p);
6933 mono_array_set (arr, guint64, i, val);
6937 case MONO_TYPE_CLASS:
6938 case MONO_TYPE_OBJECT:
6939 case MONO_TYPE_STRING:
6940 for (i = 0; i < alen; i++) {
6941 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6942 mono_array_setref (arr, i, item);
6946 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
6952 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6958 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6960 static MonoClass *klass;
6961 static MonoMethod *ctor;
6963 void *params [2], *unboxed;
6966 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6968 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6970 params [0] = mono_type_get_object (mono_domain_get (), t);
6972 retval = mono_object_new (mono_domain_get (), klass);
6973 unboxed = mono_object_unbox (retval);
6974 mono_runtime_invoke (ctor, unboxed, params, NULL);
6980 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6982 static MonoClass *klass;
6983 static MonoMethod *ctor;
6985 void *unboxed, *params [2];
6988 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6990 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6993 params [1] = typedarg;
6994 retval = mono_object_new (mono_domain_get (), klass);
6995 unboxed = mono_object_unbox (retval);
6996 mono_runtime_invoke (ctor, unboxed, params, NULL);
7002 type_is_reference (MonoType *type)
7004 switch (type->type) {
7005 case MONO_TYPE_BOOLEAN:
7006 case MONO_TYPE_CHAR:
7019 case MONO_TYPE_VALUETYPE:
7027 free_param_data (MonoMethodSignature *sig, void **params) {
7029 for (i = 0; i < sig->param_count; ++i) {
7030 if (!type_is_reference (sig->params [i]))
7031 g_free (params [i]);
7036 * Find the field index in the metadata FieldDef table.
7039 find_field_index (MonoClass *klass, MonoClassField *field) {
7042 for (i = 0; i < klass->field.count; ++i) {
7043 if (field == &klass->fields [i])
7044 return klass->field.first + 1 + i;
7050 * Find the property index in the metadata Property table.
7053 find_property_index (MonoClass *klass, MonoProperty *property) {
7056 for (i = 0; i < klass->property.count; ++i) {
7057 if (property == &klass->properties [i])
7058 return klass->property.first + 1 + i;
7064 * Find the event index in the metadata Event table.
7067 find_event_index (MonoClass *klass, MonoEvent *event) {
7070 for (i = 0; i < klass->event.count; ++i) {
7071 if (event == &klass->events [i])
7072 return klass->event.first + 1 + i;
7078 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7080 const char *p = (const char*)data;
7082 guint32 i, j, num_named;
7086 mono_class_init (method->klass);
7089 attr = mono_object_new (mono_domain_get (), method->klass);
7090 mono_runtime_invoke (method, attr, NULL, NULL);
7094 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7097 /*g_print ("got attr %s\n", method->klass->name);*/
7099 /* Allocate using alloca so it gets GC tracking */
7100 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7104 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7105 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7109 attr = mono_object_new (mono_domain_get (), method->klass);
7110 mono_runtime_invoke (method, attr, params, NULL);
7111 free_param_data (method->signature, params);
7112 num_named = read16 (named);
7114 for (j = 0; j < num_named; j++) {
7116 char *name, named_type, data_type;
7117 named_type = *named++;
7118 data_type = *named++; /* type of data */
7119 if (data_type == MONO_TYPE_SZARRAY)
7120 data_type = *named++;
7121 if (data_type == MONO_TYPE_ENUM) {
7124 type_len = mono_metadata_decode_blob_size (named, &named);
7125 type_name = g_malloc (type_len + 1);
7126 memcpy (type_name, named, type_len);
7127 type_name [type_len] = 0;
7129 /* FIXME: lookup the type and check type consistency */
7132 name_len = mono_metadata_decode_blob_size (named, &named);
7133 name = g_malloc (name_len + 1);
7134 memcpy (name, named, name_len);
7135 name [name_len] = 0;
7137 if (named_type == 0x53) {
7138 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7139 void *val = load_cattr_value (image, field->type, named, &named);
7140 mono_field_set_value (attr, field, val);
7141 if (!type_is_reference (field->type))
7143 } else if (named_type == 0x54) {
7146 MonoType *prop_type;
7148 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7149 /* can we have more that 1 arg in a custom attr named property? */
7150 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7151 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7152 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7153 mono_property_set_value (prop, attr, pparams, NULL);
7154 if (!type_is_reference (prop_type))
7155 g_free (pparams [0]);
7164 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7166 MonoArray *typedargs, *namedargs;
7167 MonoClass *attrklass;
7168 static MonoMethod *ctor;
7171 const char *p = (const char*)data;
7173 guint32 i, j, num_named;
7176 mono_class_init (method->klass);
7179 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7181 domain = mono_domain_get ();
7183 /* This is for Attributes with no parameters */
7184 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7185 params [0] = mono_method_get_object (domain, method, NULL);
7186 params [1] = params [2] = NULL;
7187 mono_runtime_invoke (method, attr, params, NULL);
7191 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7194 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7198 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7199 MonoObject *obj, *typedarg;
7202 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7203 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7204 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7205 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7206 mono_array_setref (typedargs, i, typedarg);
7208 if (!type_is_reference (mono_method_signature (method)->params [i]))
7213 num_named = read16 (named);
7214 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7216 attrklass = method->klass;
7217 for (j = 0; j < num_named; j++) {
7219 char *name, named_type, data_type;
7220 named_type = *named++;
7221 data_type = *named++; /* type of data */
7222 if (data_type == MONO_TYPE_SZARRAY)
7223 data_type = *named++;
7224 if (data_type == MONO_TYPE_ENUM) {
7227 type_len = mono_metadata_decode_blob_size (named, &named);
7228 type_name = g_malloc (type_len + 1);
7229 memcpy (type_name, named, type_len);
7230 type_name [type_len] = 0;
7232 /* FIXME: lookup the type and check type consistency */
7235 name_len = mono_metadata_decode_blob_size (named, &named);
7236 name = g_malloc (name_len + 1);
7237 memcpy (name, named, name_len);
7238 name [name_len] = 0;
7240 if (named_type == 0x53) {
7241 MonoObject *obj, *typedarg, *namedarg;
7242 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7243 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7245 minfo = mono_field_get_object (domain, NULL, field);
7246 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7247 typedarg = create_cattr_typed_arg (field->type, obj);
7248 namedarg = create_cattr_named_arg (minfo, typedarg);
7249 mono_array_setref (namedargs, j, namedarg);
7250 if (!type_is_reference (field->type))
7252 } else if (named_type == 0x54) {
7253 MonoObject *obj, *typedarg, *namedarg;
7254 MonoType *prop_type;
7256 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7258 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7259 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7260 minfo = mono_property_get_object (domain, NULL, prop);
7261 val = load_cattr_value (image, prop_type, named, &named);
7262 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7263 typedarg = create_cattr_typed_arg (prop_type, obj);
7264 namedarg = create_cattr_named_arg (minfo, typedarg);
7265 mono_array_setref (namedargs, j, namedarg);
7266 if (!type_is_reference (prop_type))
7271 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7272 params [0] = mono_method_get_object (domain, method, NULL);
7273 params [1] = typedargs;
7274 params [2] = namedargs;
7275 mono_runtime_invoke (ctor, attr, params, NULL);
7280 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7286 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7287 for (i = 0; i < cinfo->num_attrs; ++i) {
7288 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7289 mono_array_setref (result, i, attr);
7295 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7302 for (i = 0; i < cinfo->num_attrs; ++i) {
7303 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7307 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7309 for (i = 0; i < cinfo->num_attrs; ++i) {
7310 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7311 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7312 mono_array_setref (result, n, attr);
7320 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7326 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7327 for (i = 0; i < cinfo->num_attrs; ++i) {
7328 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7329 mono_array_setref (result, i, attr);
7335 * mono_custom_attrs_from_index:
7337 * Returns: NULL if no attributes are found or if a loading error occurs.
7340 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7342 guint32 mtoken, i, len;
7343 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7345 MonoCustomAttrInfo *ainfo;
7346 GList *tmp, *list = NULL;
7349 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7351 i = mono_metadata_custom_attrs_from_index (image, idx);
7355 while (i < ca->rows) {
7356 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7358 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7361 len = g_list_length (list);
7364 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7365 ainfo->num_attrs = len;
7366 ainfo->image = image;
7367 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7368 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7369 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7370 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7371 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7372 mtoken |= MONO_TOKEN_METHOD_DEF;
7374 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7375 mtoken |= MONO_TOKEN_MEMBER_REF;
7378 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7381 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7382 if (!ainfo->attrs [i].ctor) {
7383 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7388 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7389 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7390 ainfo->attrs [i].data = (guchar*)data;
7398 mono_custom_attrs_from_method (MonoMethod *method)
7400 MonoCustomAttrInfo *cinfo;
7404 * An instantiated method has the same cattrs as the generic method definition.
7406 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7407 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7409 if (method->is_inflated)
7410 method = ((MonoMethodInflated *) method)->declaring;
7412 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (method)))
7414 idx = mono_method_get_index (method);
7415 idx <<= MONO_CUSTOM_ATTR_BITS;
7416 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7417 return mono_custom_attrs_from_index (method->klass->image, idx);
7421 mono_custom_attrs_from_class (MonoClass *klass)
7423 MonoCustomAttrInfo *cinfo;
7426 if (klass->generic_class)
7427 klass = klass->generic_class->container_class;
7429 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (klass)))
7431 idx = mono_metadata_token_index (klass->type_token);
7432 idx <<= MONO_CUSTOM_ATTR_BITS;
7433 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7434 return mono_custom_attrs_from_index (klass->image, idx);
7438 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7440 MonoCustomAttrInfo *cinfo;
7443 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (assembly)))
7445 idx = 1; /* there is only one assembly */
7446 idx <<= MONO_CUSTOM_ATTR_BITS;
7447 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7448 return mono_custom_attrs_from_index (assembly->image, idx);
7451 static MonoCustomAttrInfo*
7452 mono_custom_attrs_from_module (MonoImage *image)
7454 MonoCustomAttrInfo *cinfo;
7457 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (image)))
7459 idx = 1; /* there is only one module */
7460 idx <<= MONO_CUSTOM_ATTR_BITS;
7461 idx |= MONO_CUSTOM_ATTR_MODULE;
7462 return mono_custom_attrs_from_index (image, idx);
7466 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7468 MonoCustomAttrInfo *cinfo;
7471 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (property)))
7473 idx = find_property_index (klass, property);
7474 idx <<= MONO_CUSTOM_ATTR_BITS;
7475 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7476 return mono_custom_attrs_from_index (klass->image, idx);
7480 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7482 MonoCustomAttrInfo *cinfo;
7485 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (event)))
7487 idx = find_event_index (klass, event);
7488 idx <<= MONO_CUSTOM_ATTR_BITS;
7489 idx |= MONO_CUSTOM_ATTR_EVENT;
7490 return mono_custom_attrs_from_index (klass->image, idx);
7494 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7496 MonoCustomAttrInfo *cinfo;
7499 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (field)))
7501 idx = find_field_index (klass, field);
7502 idx <<= MONO_CUSTOM_ATTR_BITS;
7503 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7504 return mono_custom_attrs_from_index (klass->image, idx);
7508 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7511 guint32 i, idx, method_index;
7512 guint32 param_list, param_last, param_pos, found;
7514 MonoReflectionMethodAux *aux;
7517 * An instantiated method has the same cattrs as the generic method definition.
7519 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7520 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7522 if (method->is_inflated)
7523 method = ((MonoMethodInflated *) method)->declaring;
7525 if (method->klass->image->dynamic) {
7526 MonoCustomAttrInfo *res, *ainfo;
7529 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7530 if (!aux || !aux->param_cattr)
7533 /* Need to copy since it will be freed later */
7534 ainfo = aux->param_cattr [param];
7535 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7536 res = g_malloc0 (size);
7537 memcpy (res, ainfo, size);
7541 image = method->klass->image;
7542 method_index = mono_method_get_index (method);
7543 ca = &image->tables [MONO_TABLE_METHOD];
7545 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7546 if (method_index == ca->rows) {
7547 ca = &image->tables [MONO_TABLE_PARAM];
7548 param_last = ca->rows + 1;
7550 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7551 ca = &image->tables [MONO_TABLE_PARAM];
7554 for (i = param_list; i < param_last; ++i) {
7555 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7556 if (param_pos == param) {
7564 idx <<= MONO_CUSTOM_ATTR_BITS;
7565 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7566 return mono_custom_attrs_from_index (image, idx);
7570 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7574 for (i = 0; i < ainfo->num_attrs; ++i) {
7575 klass = ainfo->attrs [i].ctor->klass;
7576 if (mono_class_has_parent (klass, attr_klass))
7583 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7590 for (i = 0; i < ainfo->num_attrs; ++i) {
7591 klass = ainfo->attrs [i].ctor->klass;
7592 if (mono_class_has_parent (klass, attr_klass)) {
7597 if (attr_index == -1)
7600 attrs = mono_custom_attrs_construct (ainfo);
7602 return mono_array_get (attrs, MonoObject*, attr_index);
7608 * mono_reflection_get_custom_attrs_info:
7609 * @obj: a reflection object handle
7611 * Return the custom attribute info for attributes defined for the
7612 * reflection handle @obj. The objects.
7615 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7618 MonoCustomAttrInfo *cinfo = NULL;
7620 klass = obj->vtable->klass;
7621 if (klass == mono_defaults.monotype_class) {
7622 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7623 klass = mono_class_from_mono_type (rtype->type);
7624 cinfo = mono_custom_attrs_from_class (klass);
7625 } else if (strcmp ("Assembly", klass->name) == 0) {
7626 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7627 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7628 } else if (strcmp ("Module", klass->name) == 0) {
7629 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7630 cinfo = mono_custom_attrs_from_module (module->image);
7631 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7632 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7633 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7634 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7635 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7636 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7637 } else if (strcmp ("MonoField", klass->name) == 0) {
7638 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7639 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7640 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7641 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7642 cinfo = mono_custom_attrs_from_method (rmethod->method);
7643 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7644 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7645 cinfo = mono_custom_attrs_from_method (rmethod->method);
7646 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7647 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7648 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7649 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7650 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7651 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7652 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7653 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7654 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7655 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7656 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7657 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7658 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7659 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7660 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7661 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7662 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7663 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7664 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7665 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7666 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7667 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7668 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
7669 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
7670 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
7671 } else { /* handle other types here... */
7672 g_error ("get custom attrs not yet supported for %s", klass->name);
7679 * mono_reflection_get_custom_attrs_by_type:
7680 * @obj: a reflection object handle
7682 * Return an array with all the custom attributes defined of the
7683 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7684 * of that type are returned. The objects are fully build. Return NULL if a loading error
7688 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7691 MonoCustomAttrInfo *cinfo;
7693 cinfo = mono_reflection_get_custom_attrs_info (obj);
7696 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7698 result = mono_custom_attrs_construct (cinfo);
7700 mono_custom_attrs_free (cinfo);
7702 if (mono_loader_get_last_error ())
7704 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
7711 * mono_reflection_get_custom_attrs:
7712 * @obj: a reflection object handle
7714 * Return an array with all the custom attributes defined of the
7715 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
7719 mono_reflection_get_custom_attrs (MonoObject *obj)
7721 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7725 * mono_reflection_get_custom_attrs_data:
7726 * @obj: a reflection obj handle
7728 * Returns an array of System.Reflection.CustomAttributeData,
7729 * which include information about attributes reflected on
7730 * types loaded using the Reflection Only methods
7733 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7736 MonoCustomAttrInfo *cinfo;
7738 cinfo = mono_reflection_get_custom_attrs_info (obj);
7740 result = mono_custom_attrs_data_construct (cinfo);
7742 mono_custom_attrs_free (cinfo);
7744 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
7749 static MonoReflectionType*
7750 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
7752 MonoMethod *method_get_underlying_system_type;
7754 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
7755 mono_class_get_method_from_name (mono_object_class (t),
7756 "get_UnderlyingSystemType",
7758 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
7762 mono_reflection_type_get_handle (MonoReflectionType* t)
7767 t = mono_reflection_type_get_underlying_system_type (t);
7775 * LOCKING: Assumes the loader lock is held.
7777 static MonoMethodSignature*
7778 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7779 MonoMethodSignature *sig;
7782 count = parameters? mono_array_length (parameters): 0;
7784 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7785 sig->param_count = count;
7786 sig->sentinelpos = -1; /* FIXME */
7787 for (i = 0; i < count; ++i) {
7788 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7789 sig->params [i] = mono_reflection_type_get_handle (pt);
7795 * LOCKING: Assumes the loader lock is held.
7797 static MonoMethodSignature*
7798 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7799 MonoMethodSignature *sig;
7801 sig = parameters_to_signature (mp, ctor->parameters);
7802 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7803 sig->ret = &mono_defaults.void_class->byval_arg;
7808 * LOCKING: Assumes the loader lock is held.
7810 static MonoMethodSignature*
7811 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7812 MonoMethodSignature *sig;
7814 sig = parameters_to_signature (mp, method->parameters);
7815 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7816 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7817 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7821 static MonoMethodSignature*
7822 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7823 MonoMethodSignature *sig;
7825 sig = parameters_to_signature (NULL, method->parameters);
7826 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7827 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7828 sig->generic_param_count = 0;
7833 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7835 MonoClass *klass = mono_object_class (prop);
7836 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7837 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7838 *name = mono_string_to_utf8 (pb->name);
7839 *type = pb->type->type;
7841 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7842 *name = g_strdup (p->property->name);
7843 if (p->property->get)
7844 *type = mono_method_signature (p->property->get)->ret;
7846 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7851 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7853 MonoClass *klass = mono_object_class (field);
7854 if (strcmp (klass->name, "FieldBuilder") == 0) {
7855 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7856 *name = mono_string_to_utf8 (fb->name);
7857 *type = fb->type->type;
7859 MonoReflectionField *f = (MonoReflectionField *)field;
7860 *name = g_strdup (f->field->name);
7861 *type = f->field->type;
7866 * Encode a value in a custom attribute stream of bytes.
7867 * The value to encode is either supplied as an object in argument val
7868 * (valuetypes are boxed), or as a pointer to the data in the
7870 * @type represents the type of the value
7871 * @buffer is the start of the buffer
7872 * @p the current position in the buffer
7873 * @buflen contains the size of the buffer and is used to return the new buffer size
7874 * if this needs to be realloced.
7875 * @retbuffer and @retp return the start and the position of the buffer
7878 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7880 MonoTypeEnum simple_type;
7882 if ((p-buffer) + 10 >= *buflen) {
7885 newbuf = g_realloc (buffer, *buflen);
7886 p = newbuf + (p-buffer);
7890 argval = ((char*)arg + sizeof (MonoObject));
7891 simple_type = type->type;
7893 switch (simple_type) {
7894 case MONO_TYPE_BOOLEAN:
7899 case MONO_TYPE_CHAR:
7902 swap_with_size (p, argval, 2, 1);
7908 swap_with_size (p, argval, 4, 1);
7912 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
7922 swap_with_size (p, argval, 8, 1);
7928 swap_with_size (p, argval, 8, 1);
7931 case MONO_TYPE_VALUETYPE:
7932 if (type->data.klass->enumtype) {
7933 simple_type = type->data.klass->enum_basetype->type;
7936 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7939 case MONO_TYPE_STRING: {
7946 str = mono_string_to_utf8 ((MonoString*)arg);
7947 slen = strlen (str);
7948 if ((p-buffer) + 10 + slen >= *buflen) {
7952 newbuf = g_realloc (buffer, *buflen);
7953 p = newbuf + (p-buffer);
7956 mono_metadata_encode_value (slen, p, &p);
7957 memcpy (p, str, slen);
7962 case MONO_TYPE_CLASS: {
7970 k = mono_object_class (arg);
7971 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7972 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
7973 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
7976 if (rt && (rtc = mono_object_class (rt)) &&
7977 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
7978 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
7979 arg = (MonoObject *) rt;
7982 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
7985 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7986 slen = strlen (str);
7987 if ((p-buffer) + 10 + slen >= *buflen) {
7991 newbuf = g_realloc (buffer, *buflen);
7992 p = newbuf + (p-buffer);
7995 mono_metadata_encode_value (slen, p, &p);
7996 memcpy (p, str, slen);
8001 case MONO_TYPE_SZARRAY: {
8003 MonoClass *eclass, *arg_eclass;
8006 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8009 len = mono_array_length ((MonoArray*)arg);
8011 *p++ = (len >> 8) & 0xff;
8012 *p++ = (len >> 16) & 0xff;
8013 *p++ = (len >> 24) & 0xff;
8015 *retbuffer = buffer;
8016 eclass = type->data.klass;
8017 arg_eclass = mono_object_class (arg)->element_class;
8020 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8021 eclass = mono_defaults.object_class;
8023 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8024 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8025 int elsize = mono_class_array_element_size (arg_eclass);
8026 for (i = 0; i < len; ++i) {
8027 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8030 } else if (eclass->valuetype && arg_eclass->valuetype) {
8031 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8032 int elsize = mono_class_array_element_size (eclass);
8033 for (i = 0; i < len; ++i) {
8034 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8038 for (i = 0; i < len; ++i) {
8039 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8044 case MONO_TYPE_OBJECT: {
8050 * The parameter type is 'object' but the type of the actual
8051 * argument is not. So we have to add type information to the blob
8052 * too. This is completely undocumented in the spec.
8056 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8061 klass = mono_object_class (arg);
8063 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8066 } else if (klass->enumtype) {
8068 } else if (klass == mono_defaults.string_class) {
8069 simple_type = MONO_TYPE_STRING;
8072 } else if (klass->rank == 1) {
8074 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8075 /* See Partition II, Appendix B3 */
8078 *p++ = klass->element_class->byval_arg.type;
8079 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8081 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8082 *p++ = simple_type = klass->byval_arg.type;
8085 g_error ("unhandled type in custom attr");
8087 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8088 slen = strlen (str);
8089 if ((p-buffer) + 10 + slen >= *buflen) {
8093 newbuf = g_realloc (buffer, *buflen);
8094 p = newbuf + (p-buffer);
8097 mono_metadata_encode_value (slen, p, &p);
8098 memcpy (p, str, slen);
8101 simple_type = klass->enum_basetype->type;
8105 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8108 *retbuffer = buffer;
8112 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8114 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8115 char *str = type_get_qualified_name (type, NULL);
8116 int slen = strlen (str);
8120 * This seems to be optional...
8123 mono_metadata_encode_value (slen, p, &p);
8124 memcpy (p, str, slen);
8127 } else if (type->type == MONO_TYPE_OBJECT) {
8129 } else if (type->type == MONO_TYPE_CLASS) {
8130 /* it should be a type: encode_cattr_value () has the check */
8133 mono_metadata_encode_value (type->type, p, &p);
8134 if (type->type == MONO_TYPE_SZARRAY)
8135 /* See the examples in Partition VI, Annex B */
8136 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8143 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8146 /* Preallocate a large enough buffer */
8147 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8148 char *str = type_get_qualified_name (type, NULL);
8151 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8152 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8158 len += strlen (name);
8160 if ((p-buffer) + 20 + len >= *buflen) {
8164 newbuf = g_realloc (buffer, *buflen);
8165 p = newbuf + (p-buffer);
8169 encode_field_or_prop_type (type, p, &p);
8171 len = strlen (name);
8172 mono_metadata_encode_value (len, p, &p);
8173 memcpy (p, name, len);
8175 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8177 *retbuffer = buffer;
8181 * mono_reflection_get_custom_attrs_blob:
8182 * @ctor: custom attribute constructor
8183 * @ctorArgs: arguments o the constructor
8189 * Creates the blob of data that needs to be saved in the metadata and that represents
8190 * the custom attributed described by @ctor, @ctorArgs etc.
8191 * Returns: a Byte array representing the blob of data.
8194 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8197 MonoMethodSignature *sig;
8202 MONO_ARCH_SAVE_REGS;
8204 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8205 /* sig is freed later so allocate it in the heap */
8206 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8208 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8211 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8213 p = buffer = g_malloc (buflen);
8214 /* write the prolog */
8217 for (i = 0; i < sig->param_count; ++i) {
8218 arg = mono_array_get (ctorArgs, MonoObject*, i);
8219 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8223 i += mono_array_length (properties);
8225 i += mono_array_length (fields);
8227 *p++ = (i >> 8) & 0xff;
8230 for (i = 0; i < mono_array_length (properties); ++i) {
8234 prop = mono_array_get (properties, gpointer, i);
8235 get_prop_name_and_type (prop, &pname, &ptype);
8236 *p++ = 0x54; /* PROPERTY signature */
8237 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8244 for (i = 0; i < mono_array_length (fields); ++i) {
8248 field = mono_array_get (fields, gpointer, i);
8249 get_field_name_and_type (field, &fname, &ftype);
8250 *p++ = 0x53; /* FIELD signature */
8251 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8256 g_assert (p - buffer <= buflen);
8257 buflen = p - buffer;
8258 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8259 p = mono_array_addr (result, char, 0);
8260 memcpy (p, buffer, buflen);
8262 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8268 static void* reflection_info_desc = NULL;
8269 #define MOVING_GC_REGISTER(addr) do { \
8270 if (!reflection_info_desc) { \
8272 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8274 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8277 #define MOVING_GC_REGISTER(addr)
8281 * mono_reflection_setup_internal_class:
8282 * @tb: a TypeBuilder object
8284 * Creates a MonoClass that represents the TypeBuilder.
8285 * This is a trick that lets us simplify a lot of reflection code
8286 * (and will allow us to support Build and Run assemblies easier).
8289 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8291 MonoClass *klass, *parent;
8293 MONO_ARCH_SAVE_REGS;
8295 mono_loader_lock ();
8298 /* check so we can compile corlib correctly */
8299 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8300 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8301 parent = tb->parent->type->data.klass;
8303 parent = my_mono_class_from_mono_type (tb->parent->type);
8309 /* the type has already being created: it means we just have to change the parent */
8310 if (tb->type.type) {
8311 klass = mono_class_from_mono_type (tb->type.type);
8312 klass->parent = NULL;
8313 /* fool mono_class_setup_parent */
8314 klass->supertypes = NULL;
8315 mono_class_setup_parent (klass, parent);
8316 mono_class_setup_mono_type (klass);
8317 mono_loader_unlock ();
8321 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8323 klass->image = &tb->module->dynamic_image->image;
8325 klass->inited = 1; /* we lie to the runtime */
8326 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8327 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8328 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8329 klass->flags = tb->attrs;
8331 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8333 klass->element_class = klass;
8335 MOVING_GC_REGISTER (&klass->reflection_info);
8336 klass->reflection_info = tb;
8338 /* Put into cache so mono_class_get () will find it */
8339 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8341 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8342 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8344 if (parent != NULL) {
8345 mono_class_setup_parent (klass, parent);
8346 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8347 const char *old_n = klass->name;
8348 /* trick to get relative numbering right when compiling corlib */
8349 klass->name = "BuildingObject";
8350 mono_class_setup_parent (klass, mono_defaults.object_class);
8351 klass->name = old_n;
8354 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8355 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8356 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8357 klass->instance_size = sizeof (MonoObject);
8358 klass->size_inited = 1;
8359 mono_class_setup_vtable_general (klass, NULL, 0);
8362 mono_class_setup_mono_type (klass);
8364 mono_class_setup_supertypes (klass);
8367 * FIXME: handle interfaces.
8370 tb->type.type = &klass->byval_arg;
8372 if (tb->nesting_type) {
8373 g_assert (tb->nesting_type->type);
8374 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8377 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8379 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8381 mono_loader_unlock ();
8385 * mono_reflection_setup_generic_class:
8386 * @tb: a TypeBuilder object
8388 * Setup the generic class before adding the first generic parameter.
8391 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8395 MONO_ARCH_SAVE_REGS;
8397 klass = my_mono_class_from_mono_type (tb->type.type);
8398 if (tb->generic_container)
8401 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8402 tb->generic_container->owner.klass = klass;
8406 * mono_reflection_create_generic_class:
8407 * @tb: a TypeBuilder object
8409 * Creates the generic class after all generic parameters have been added.
8412 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8417 MONO_ARCH_SAVE_REGS;
8419 klass = my_mono_class_from_mono_type (tb->type.type);
8421 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8423 if (klass->generic_container || (count == 0))
8426 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8428 klass->generic_container = tb->generic_container;
8430 klass->generic_container->type_argc = count;
8431 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8433 for (i = 0; i < count; i++) {
8434 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8435 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8436 g_assert (klass->generic_container->type_params [i].owner);
8439 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8443 * mono_reflection_create_internal_class:
8444 * @tb: a TypeBuilder object
8446 * Actually create the MonoClass that is associated with the TypeBuilder.
8449 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8453 MONO_ARCH_SAVE_REGS;
8455 klass = my_mono_class_from_mono_type (tb->type.type);
8457 mono_loader_lock ();
8458 if (klass->enumtype && klass->enum_basetype == NULL) {
8459 MonoReflectionFieldBuilder *fb;
8462 g_assert (tb->fields != NULL);
8463 g_assert (mono_array_length (tb->fields) >= 1);
8465 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8467 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8468 mono_loader_unlock ();
8472 klass->enum_basetype = fb->type->type;
8473 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8474 if (!klass->element_class)
8475 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8478 * get the element_class from the current corlib.
8480 ec = default_class_from_mono_type (klass->enum_basetype);
8481 klass->instance_size = ec->instance_size;
8482 klass->size_inited = 1;
8484 * this is almost safe to do with enums and it's needed to be able
8485 * to create objects of the enum type (for use in SetConstant).
8487 /* FIXME: Does this mean enums can't have method overrides ? */
8488 mono_class_setup_vtable_general (klass, NULL, 0);
8490 mono_loader_unlock ();
8493 static MonoMarshalSpec*
8494 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8495 MonoReflectionMarshal *minfo)
8497 MonoMarshalSpec *res;
8499 res = g_new0 (MonoMarshalSpec, 1);
8500 res->native = minfo->type;
8502 switch (minfo->type) {
8503 case MONO_NATIVE_LPARRAY:
8504 res->data.array_data.elem_type = minfo->eltype;
8505 if (minfo->has_size) {
8506 res->data.array_data.param_num = minfo->param_num;
8507 res->data.array_data.num_elem = minfo->count;
8508 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8511 res->data.array_data.param_num = -1;
8512 res->data.array_data.num_elem = -1;
8513 res->data.array_data.elem_mult = -1;
8517 case MONO_NATIVE_BYVALTSTR:
8518 case MONO_NATIVE_BYVALARRAY:
8519 res->data.array_data.num_elem = minfo->count;
8522 case MONO_NATIVE_CUSTOM:
8523 if (minfo->marshaltyperef)
8524 res->data.custom_data.custom_name =
8525 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8527 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8537 MonoReflectionMarshal*
8538 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8539 MonoMarshalSpec *spec)
8541 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8542 MonoReflectionMarshal *minfo;
8545 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8546 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8547 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8548 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8551 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8552 minfo->type = spec->native;
8554 switch (minfo->type) {
8555 case MONO_NATIVE_LPARRAY:
8556 minfo->eltype = spec->data.array_data.elem_type;
8557 minfo->count = spec->data.array_data.num_elem;
8558 minfo->param_num = spec->data.array_data.param_num;
8561 case MONO_NATIVE_BYVALTSTR:
8562 case MONO_NATIVE_BYVALARRAY:
8563 minfo->count = spec->data.array_data.num_elem;
8566 case MONO_NATIVE_CUSTOM:
8567 if (spec->data.custom_data.custom_name) {
8568 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8570 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8572 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8574 if (spec->data.custom_data.cookie)
8575 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8586 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8587 ReflectionMethodBuilder *rmb,
8588 MonoMethodSignature *sig)
8591 MonoMethodNormal *pm;
8592 MonoMarshalSpec **specs;
8593 MonoReflectionMethodAux *method_aux;
8599 * Methods created using a MethodBuilder should have their memory allocated
8600 * inside the image mempool, while dynamic methods should have their memory
8603 dynamic = rmb->refs != NULL;
8604 mp = dynamic ? NULL : klass->image->mempool;
8607 g_assert (!klass->generic_class);
8609 mono_loader_lock ();
8611 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8612 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8613 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8615 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8617 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8619 pm = (MonoMethodNormal*)m;
8621 m->dynamic = dynamic;
8623 m->flags = rmb->attrs;
8624 m->iflags = rmb->iattrs;
8625 m->name = mp_string_to_utf8 (mp, rmb->name);
8628 m->skip_visibility = rmb->skip_visibility;
8630 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8632 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8633 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8636 m->signature->pinvoke = 1;
8637 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8638 m->signature->pinvoke = 1;
8640 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8642 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8643 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8645 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8647 if (klass->image->dynamic)
8648 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8650 mono_loader_unlock ();
8653 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8654 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8655 MonoMethodHeader *header;
8657 gint32 max_stack, i;
8658 gint32 num_locals = 0;
8659 gint32 num_clauses = 0;
8663 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8664 code_size = rmb->ilgen->code_len;
8665 max_stack = rmb->ilgen->max_stack;
8666 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8667 if (rmb->ilgen->ex_handlers)
8668 num_clauses = method_count_clauses (rmb->ilgen);
8671 code = mono_array_addr (rmb->code, guint8, 0);
8672 code_size = mono_array_length (rmb->code);
8673 /* we probably need to run a verifier on the code... */
8683 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8684 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8685 header->code_size = code_size;
8686 header->code = mp_g_malloc (mp, code_size);
8687 memcpy ((char*)header->code, code, code_size);
8688 header->max_stack = max_stack;
8689 header->init_locals = rmb->init_locals;
8690 header->num_locals = num_locals;
8692 for (i = 0; i < num_locals; ++i) {
8693 MonoReflectionLocalBuilder *lb =
8694 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8696 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8697 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8700 header->num_clauses = num_clauses;
8702 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8703 rmb->ilgen, num_clauses);
8706 pm->header = header;
8709 if (rmb->generic_params) {
8710 int count = mono_array_length (rmb->generic_params);
8711 MonoGenericContainer *container;
8713 m->generic_container = container = rmb->generic_container;
8714 container->type_argc = count;
8715 container->type_params = g_new0 (MonoGenericParam, count);
8716 container->owner.method = m;
8718 for (i = 0; i < count; i++) {
8719 MonoReflectionGenericParam *gp =
8720 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8722 container->type_params [i] = *gp->type.type->data.generic_param;
8725 if (klass->generic_container) {
8726 container->parent = klass->generic_container;
8727 container->context.class_inst = klass->generic_container->context.class_inst;
8729 container->context.method_inst = mono_get_shared_generic_inst (container);
8733 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8737 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8739 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8740 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8741 for (i = 0; i < rmb->nrefs; ++i)
8742 data [i + 1] = rmb->refs [i];
8747 /* Parameter info */
8750 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8751 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8752 for (i = 0; i <= m->signature->param_count; ++i) {
8753 MonoReflectionParamBuilder *pb;
8754 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8755 if ((i > 0) && (pb->attrs)) {
8756 /* Make a copy since it might point to a shared type structure */
8757 /* FIXME: Alloc this from a mempool */
8758 m->signature->params [i - 1] = mono_metadata_type_dup (NULL, m->signature->params [i - 1]);
8759 m->signature->params [i - 1]->attrs = pb->attrs;
8762 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8763 MonoDynamicImage *assembly;
8764 guint32 idx, def_type, len;
8768 if (!method_aux->param_defaults) {
8769 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8770 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8772 assembly = (MonoDynamicImage*)klass->image;
8773 idx = encode_constant (assembly, pb->def_value, &def_type);
8774 /* Copy the data from the blob since it might get realloc-ed */
8775 p = assembly->blob.data + idx;
8776 len = mono_metadata_decode_blob_size (p, &p2);
8778 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8779 method_aux->param_default_types [i] = def_type;
8780 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8784 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
8786 if (!method_aux->param_cattr)
8787 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8788 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8794 /* Parameter marshalling */
8797 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8798 MonoReflectionParamBuilder *pb;
8799 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8800 if (pb->marshal_info) {
8802 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8803 specs [pb->position] =
8804 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8808 if (specs != NULL) {
8810 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8811 method_aux->param_marshall = specs;
8814 if (klass->image->dynamic && method_aux)
8815 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8817 mono_loader_unlock ();
8823 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8825 ReflectionMethodBuilder rmb;
8826 MonoMethodSignature *sig;
8828 mono_loader_lock ();
8829 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8830 mono_loader_unlock ();
8832 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8834 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8835 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8837 /* If we are in a generic class, we might be called multiple times from inflate_method */
8838 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
8839 /* ilgen is no longer needed */
8847 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8849 ReflectionMethodBuilder rmb;
8850 MonoMethodSignature *sig;
8852 mono_loader_lock ();
8853 sig = method_builder_to_signature (klass->image->mempool, mb);
8854 mono_loader_unlock ();
8856 reflection_methodbuilder_from_method_builder (&rmb, mb);
8858 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8859 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8861 /* If we are in a generic class, we might be called multiple times from inflate_method */
8862 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
8863 /* ilgen is no longer needed */
8869 static MonoClassField*
8870 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8872 MonoClassField *field;
8876 field = g_new0 (MonoClassField, 1);
8878 field->name = mono_string_to_utf8 (fb->name);
8880 /* FIXME: handle type modifiers */
8881 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8882 field->type->attrs = fb->attrs;
8884 field->type = fb->type->type;
8886 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8887 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8888 if (fb->offset != -1)
8889 field->offset = fb->offset;
8890 field->parent = klass;
8891 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8893 if (fb->def_value) {
8894 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8895 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8896 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8897 /* Copy the data from the blob since it might get realloc-ed */
8898 p = assembly->blob.data + idx;
8899 len = mono_metadata_decode_blob_size (p, &p2);
8901 field->data = g_malloc (len);
8902 memcpy ((gpointer)field->data, p, len);
8909 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8912 MonoReflectionTypeBuilder *tb = NULL;
8913 gboolean is_dynamic = FALSE;
8917 mono_loader_lock ();
8919 domain = mono_object_domain (type);
8921 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8922 tb = (MonoReflectionTypeBuilder *) type;
8925 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8926 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8928 tb = rgi->generic_type;
8932 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
8933 if (tb && tb->generic_container)
8934 mono_reflection_create_generic_class (tb);
8936 klass = mono_class_from_mono_type (type->type);
8937 if (!klass->generic_container) {
8938 mono_loader_unlock ();
8942 if (klass->wastypebuilder) {
8943 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8948 mono_loader_unlock ();
8950 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
8952 return &geninst->byval_arg;
8956 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
8958 MonoGenericClass *gclass;
8959 MonoGenericInst *inst;
8961 g_assert (klass->generic_container);
8963 inst = mono_metadata_get_generic_inst (type_argc, types);
8964 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
8966 return mono_generic_class_get_class (gclass);
8969 MonoReflectionMethod*
8970 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8973 MonoMethod *method, *inflated;
8974 MonoMethodInflated *imethod;
8975 MonoReflectionMethodBuilder *mb = NULL;
8976 MonoGenericContext tmp_context;
8977 MonoGenericInst *ginst;
8978 MonoType **type_argv;
8981 MONO_ARCH_SAVE_REGS;
8982 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8983 MonoReflectionTypeBuilder *tb;
8986 mb = (MonoReflectionMethodBuilder *) rmethod;
8987 tb = (MonoReflectionTypeBuilder *) mb->type;
8988 klass = mono_class_from_mono_type (tb->type.type);
8990 method = methodbuilder_to_mono_method (klass, mb);
8992 method = rmethod->method;
8995 klass = method->klass;
8997 if (method->is_inflated)
8998 method = ((MonoMethodInflated *) method)->declaring;
9000 count = mono_method_signature (method)->generic_param_count;
9001 if (count != mono_array_length (types))
9004 type_argv = g_new0 (MonoType *, count);
9005 for (i = 0; i < count; i++) {
9006 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9007 type_argv [i] = garg->type;
9009 ginst = mono_metadata_get_generic_inst (count, type_argv);
9012 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9013 tmp_context.method_inst = ginst;
9015 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9016 imethod = (MonoMethodInflated *) inflated;
9018 MOVING_GC_REGISTER (&imethod->reflection_info);
9019 imethod->reflection_info = rmethod;
9021 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9025 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
9027 MonoMethodInflated *imethod;
9028 MonoGenericContext *context;
9031 klass = mono_class_from_mono_type (type->type.type);
9032 g_assert (klass->generic_class);
9033 context = mono_class_get_context (klass);
9035 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9036 if (method->generic_container) {
9037 MOVING_GC_REGISTER (&imethod->reflection_info);
9038 imethod->reflection_info = obj;
9040 return (MonoMethod *) imethod;
9044 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9049 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9051 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9052 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9053 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9054 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9055 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9056 method = ((MonoReflectionMethod *) obj)->method;
9058 method = NULL; /* prevent compiler warning */
9059 g_assert_not_reached ();
9062 return inflate_mono_method (type, method, obj);
9066 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9067 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9070 MonoGenericClass *gclass;
9071 MonoDynamicGenericClass *dgclass;
9072 MonoClass *klass, *gklass;
9075 MONO_ARCH_SAVE_REGS;
9077 klass = mono_class_from_mono_type (type->type.type);
9078 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9079 gclass = type->type.type->data.generic_class;
9081 g_assert (gclass->is_dynamic);
9082 dgclass = (MonoDynamicGenericClass *) gclass;
9084 if (dgclass->initialized)
9087 gklass = gclass->container_class;
9088 mono_class_init (gklass);
9090 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9091 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9092 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9093 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9094 dgclass->count_events = events ? mono_array_length (events) : 0;
9096 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9097 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9098 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9099 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9100 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9102 for (i = 0; i < dgclass->count_methods; i++) {
9103 MonoObject *obj = mono_array_get (methods, gpointer, i);
9105 dgclass->methods [i] = inflate_method (type, obj);
9108 for (i = 0; i < dgclass->count_ctors; i++) {
9109 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9111 dgclass->ctors [i] = inflate_method (type, obj);
9114 for (i = 0; i < dgclass->count_fields; i++) {
9115 MonoObject *obj = mono_array_get (fields, gpointer, i);
9116 MonoClassField *field;
9117 MonoInflatedField *ifield;
9119 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9120 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9121 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9122 field = ((MonoReflectionField *) obj)->field;
9124 field = NULL; /* prevent compiler warning */
9125 g_assert_not_reached ();
9128 ifield = g_new0 (MonoInflatedField, 1);
9129 ifield->generic_type = field->type;
9130 MOVING_GC_REGISTER (&ifield->reflection_info);
9131 ifield->reflection_info = obj;
9133 dgclass->fields [i] = *field;
9134 dgclass->fields [i].parent = klass;
9135 dgclass->fields [i].generic_info = ifield;
9136 dgclass->fields [i].type = mono_class_inflate_generic_type (
9137 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9140 for (i = 0; i < dgclass->count_properties; i++) {
9141 MonoObject *obj = mono_array_get (properties, gpointer, i);
9142 MonoProperty *property = &dgclass->properties [i];
9144 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9145 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9147 property->parent = klass;
9148 property->attrs = pb->attrs;
9149 property->name = mono_string_to_utf8 (pb->name);
9151 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9153 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9154 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9155 *property = *((MonoReflectionProperty *) obj)->property;
9158 property->get = inflate_mono_method (type, property->get, NULL);
9160 property->set = inflate_mono_method (type, property->set, NULL);
9162 g_assert_not_reached ();
9165 for (i = 0; i < dgclass->count_events; i++) {
9166 MonoObject *obj = mono_array_get (events, gpointer, i);
9167 MonoEvent *event = &dgclass->events [i];
9169 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9170 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9172 event->parent = klass;
9173 event->attrs = eb->attrs;
9174 event->name = mono_string_to_utf8 (eb->name);
9176 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9177 if (eb->remove_method)
9178 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9179 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9180 *event = *((MonoReflectionEvent *) obj)->event;
9183 event->add = inflate_mono_method (type, event->add, NULL);
9185 event->remove = inflate_mono_method (type, event->remove, NULL);
9187 g_assert_not_reached ();
9190 dgclass->initialized = TRUE;
9194 ensure_runtime_vtable (MonoClass *klass)
9196 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9199 if (!tb || klass->wastypebuilder)
9202 ensure_runtime_vtable (klass->parent);
9204 num = tb->ctors? mono_array_length (tb->ctors): 0;
9205 num += tb->num_methods;
9206 klass->method.count = num;
9207 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9208 num = tb->ctors? mono_array_length (tb->ctors): 0;
9209 for (i = 0; i < num; ++i)
9210 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9211 num = tb->num_methods;
9213 for (i = 0; i < num; ++i)
9214 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9216 if (tb->interfaces) {
9217 klass->interface_count = mono_array_length (tb->interfaces);
9218 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9219 for (i = 0; i < klass->interface_count; ++i) {
9220 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9221 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9225 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9226 for (i = 0; i < klass->method.count; ++i)
9227 klass->methods [i]->slot = i;
9229 mono_class_setup_interface_offsets (klass);
9233 * The generic vtable is needed even if image->run is not set since some
9234 * runtime code like ves_icall_Type_GetMethodsByName depends on
9235 * method->slot being defined.
9239 * tb->methods could not be freed since it is used for determining
9240 * overrides during dynamic vtable construction.
9245 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9247 MonoReflectionTypeBuilder *tb;
9253 g_assert (klass->image->dynamic);
9255 if (!klass->reflection_info)
9258 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9260 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9264 for (i = 0; i < tb->num_methods; ++i) {
9265 MonoReflectionMethodBuilder *mb =
9266 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9267 if (mb->override_method)
9273 *overrides = g_new0 (MonoMethod*, onum * 2);
9276 for (i = 0; i < tb->num_methods; ++i) {
9277 MonoReflectionMethodBuilder *mb =
9278 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9279 if (mb->override_method) {
9280 (*overrides) [onum * 2] =
9281 mb->override_method->method;
9282 (*overrides) [onum * 2 + 1] =
9285 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9286 g_assert (mb->override_method->method);
9287 g_assert (mb->mhandle);
9294 *num_overrides = onum;
9298 typebuilder_setup_fields (MonoClass *klass)
9300 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9301 MonoReflectionFieldBuilder *fb;
9302 MonoClassField *field;
9307 klass->field.count = tb->num_fields;
9308 klass->field.first = 0;
9310 if (!klass->field.count)
9313 klass->fields = g_new0 (MonoClassField, klass->field.count);
9315 for (i = 0; i < klass->field.count; ++i) {
9316 fb = mono_array_get (tb->fields, gpointer, i);
9317 field = &klass->fields [i];
9318 field->name = mono_string_to_utf8 (fb->name);
9320 /* FIXME: handle type modifiers */
9321 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9322 field->type->attrs = fb->attrs;
9324 field->type = fb->type->type;
9326 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9327 field->data = mono_array_addr (fb->rva_data, char, 0);
9328 if (fb->offset != -1)
9329 field->offset = fb->offset;
9330 field->parent = klass;
9332 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9334 if (fb->def_value) {
9335 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9336 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9337 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9338 /* Copy the data from the blob since it might get realloc-ed */
9339 p = assembly->blob.data + idx;
9340 len = mono_metadata_decode_blob_size (p, &p2);
9342 field->data = g_malloc (len);
9343 memcpy ((gpointer)field->data, p, len);
9346 mono_class_layout_fields (klass);
9350 typebuilder_setup_properties (MonoClass *klass)
9352 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9353 MonoReflectionPropertyBuilder *pb;
9356 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9357 klass->property.first = 0;
9359 klass->properties = g_new0 (MonoProperty, klass->property.count);
9360 for (i = 0; i < klass->property.count; ++i) {
9361 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9362 klass->properties [i].parent = klass;
9363 klass->properties [i].attrs = pb->attrs;
9364 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9366 klass->properties [i].get = pb->get_method->mhandle;
9368 klass->properties [i].set = pb->set_method->mhandle;
9370 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9374 MonoReflectionEvent *
9375 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9377 MonoEvent *event = g_new0 (MonoEvent, 1);
9381 klass = my_mono_class_from_mono_type (tb->type.type);
9383 event->parent = klass;
9384 event->attrs = eb->attrs;
9385 event->name = mono_string_to_utf8 (eb->name);
9387 event->add = eb->add_method->mhandle;
9388 if (eb->remove_method)
9389 event->remove = eb->remove_method->mhandle;
9390 if (eb->raise_method)
9391 event->raise = eb->raise_method->mhandle;
9393 if (eb->other_methods) {
9394 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9395 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9396 MonoReflectionMethodBuilder *mb =
9397 mono_array_get (eb->other_methods,
9398 MonoReflectionMethodBuilder*, j);
9399 event->other [j] = mb->mhandle;
9403 return mono_event_get_object (mono_object_domain (tb), klass, event);
9407 typebuilder_setup_events (MonoClass *klass)
9409 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9410 MonoReflectionEventBuilder *eb;
9413 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9414 klass->event.first = 0;
9416 klass->events = g_new0 (MonoEvent, klass->event.count);
9417 for (i = 0; i < klass->event.count; ++i) {
9418 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9419 klass->events [i].parent = klass;
9420 klass->events [i].attrs = eb->attrs;
9421 klass->events [i].name = mono_string_to_utf8 (eb->name);
9423 klass->events [i].add = eb->add_method->mhandle;
9424 if (eb->remove_method)
9425 klass->events [i].remove = eb->remove_method->mhandle;
9426 if (eb->raise_method)
9427 klass->events [i].raise = eb->raise_method->mhandle;
9429 if (eb->other_methods) {
9430 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9431 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9432 MonoReflectionMethodBuilder *mb =
9433 mono_array_get (eb->other_methods,
9434 MonoReflectionMethodBuilder*, j);
9435 klass->events [i].other [j] = mb->mhandle;
9442 remove_instantiations_of (gpointer key,
9446 MonoType *type = (MonoType*)key;
9447 MonoClass *klass = (MonoClass*)user_data;
9449 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
9456 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9460 MonoReflectionType* res;
9463 MONO_ARCH_SAVE_REGS;
9465 domain = mono_object_domain (tb);
9466 klass = my_mono_class_from_mono_type (tb->type.type);
9468 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9471 * we need to lock the domain because the lock will be taken inside
9472 * So, we need to keep the locking order correct.
9474 mono_domain_lock (domain);
9475 mono_loader_lock ();
9476 if (klass->wastypebuilder) {
9477 mono_loader_unlock ();
9478 mono_domain_unlock (domain);
9479 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9482 * Fields to set in klass:
9483 * the various flags: delegate/unicode/contextbound etc.
9485 klass->flags = tb->attrs;
9486 klass->has_cctor = 1;
9487 klass->has_finalize = 1;
9490 if (!((MonoDynamicImage*)klass->image)->run) {
9491 if (klass->generic_container) {
9492 /* FIXME: The code below can't handle generic classes */
9493 klass->wastypebuilder = TRUE;
9494 mono_loader_unlock ();
9495 mono_domain_unlock (domain);
9496 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9501 /* enums are done right away */
9502 if (!klass->enumtype)
9503 ensure_runtime_vtable (klass);
9506 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9507 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9508 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9512 /* fields and object layout */
9513 if (klass->parent) {
9514 if (!klass->parent->size_inited)
9515 mono_class_init (klass->parent);
9516 klass->instance_size = klass->parent->instance_size;
9517 klass->sizes.class_size = 0;
9518 klass->min_align = klass->parent->min_align;
9519 /* if the type has no fields we won't call the field_setup
9520 * routine which sets up klass->has_references.
9522 klass->has_references |= klass->parent->has_references;
9524 klass->instance_size = sizeof (MonoObject);
9525 klass->min_align = 1;
9528 /* FIXME: handle packing_size and instance_size */
9529 typebuilder_setup_fields (klass);
9531 typebuilder_setup_properties (klass);
9533 typebuilder_setup_events (klass);
9535 klass->wastypebuilder = TRUE;
9538 * If we are a generic TypeBuilder, there might be instantiations in the type cache
9539 * which have type System.Reflection.MonoGenericClass, but after the type is created,
9540 * we want to return normal System.MonoType objects, so clear these out from the cache.
9542 if (domain->type_hash && klass->generic_container)
9543 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
9545 mono_loader_unlock ();
9546 mono_domain_unlock (domain);
9548 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
9549 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
9550 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
9553 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9554 g_assert (res != (MonoReflectionType*)tb);
9560 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9562 MonoGenericParam *param;
9565 MONO_ARCH_SAVE_REGS;
9567 param = g_new0 (MonoGenericParam, 1);
9569 if (gparam->mbuilder) {
9570 if (!gparam->mbuilder->generic_container) {
9571 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9572 gparam->mbuilder->generic_container->is_method = TRUE;
9574 param->owner = gparam->mbuilder->generic_container;
9575 } else if (gparam->tbuilder) {
9576 g_assert (gparam->tbuilder->generic_container);
9577 param->owner = gparam->tbuilder->generic_container;
9580 param->name = mono_string_to_utf8 (gparam->name);
9581 param->num = gparam->index;
9583 image = &gparam->tbuilder->module->dynamic_image->image;
9584 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9586 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
9587 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9589 gparam->type.type = g_new0 (MonoType, 1);
9590 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9591 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9592 gparam->type.type->data.generic_param = param;
9596 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9598 MonoDynamicImage *assembly = sig->module->dynamic_image;
9599 guint32 na = mono_array_length (sig->arguments);
9604 sigbuffer_init (&buf, 32);
9606 sigbuffer_add_value (&buf, 0x07);
9607 sigbuffer_add_value (&buf, na);
9608 for (i = 0; i < na; ++i) {
9609 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9610 encode_reflection_type (assembly, type, &buf);
9613 buflen = buf.p - buf.buf;
9614 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9615 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9616 sigbuffer_free (&buf);
9622 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9624 MonoDynamicImage *assembly = sig->module->dynamic_image;
9625 guint32 na = mono_array_length (sig->arguments);
9630 sigbuffer_init (&buf, 32);
9632 sigbuffer_add_value (&buf, 0x06);
9633 for (i = 0; i < na; ++i) {
9634 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9635 encode_reflection_type (assembly, type, &buf);
9638 buflen = buf.p - buf.buf;
9639 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9640 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9641 sigbuffer_free (&buf);
9647 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9649 ReflectionMethodBuilder rmb;
9650 MonoMethodSignature *sig;
9655 sig = dynamic_method_to_signature (mb);
9657 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9660 * Resolve references.
9663 * Every second entry in the refs array is reserved for storing handle_class,
9664 * which is needed by the ldtoken implementation in the JIT.
9666 rmb.nrefs = mb->nrefs;
9667 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9668 for (i = 0; i < mb->nrefs; i += 2) {
9669 MonoClass *handle_class;
9671 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
9673 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9674 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9676 * The referenced DynamicMethod should already be created by the managed
9677 * code, except in the case of circular references. In that case, we store
9678 * method in the refs array, and fix it up later when the referenced
9679 * DynamicMethod is created.
9681 if (method->mhandle) {
9682 ref = method->mhandle;
9684 /* FIXME: GC object stored in unmanaged memory */
9687 /* FIXME: GC object stored in unmanaged memory */
9688 method->referenced_by = g_slist_append (method->referenced_by, mb);
9690 handle_class = mono_defaults.methodhandle_class;
9692 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
9695 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9700 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9701 rmb.refs [i + 1] = handle_class;
9704 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
9706 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9708 /* Fix up refs entries pointing at us */
9709 for (l = mb->referenced_by; l; l = l->next) {
9710 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
9711 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
9714 g_assert (method->mhandle);
9716 data = (gpointer*)wrapper->method_data;
9717 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
9718 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
9719 data [i + 1] = mb->mhandle;
9722 g_slist_free (mb->referenced_by);
9726 /* ilgen is no longer needed */
9731 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
9736 mono_runtime_free_method (
9737 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
9741 * mono_reflection_lookup_dynamic_token:
9743 * Finish the Builder object pointed to by TOKEN and return the corresponding
9744 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
9745 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
9749 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
9751 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9755 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9758 g_assert_not_reached ();
9764 handle_class = &klass;
9765 return resolve_object (image, obj, handle_class, context);
9769 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
9771 gpointer result = NULL;
9773 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9774 result = mono_string_intern ((MonoString*)obj);
9775 *handle_class = NULL;
9777 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9778 MonoReflectionType *tb = (MonoReflectionType*)obj;
9780 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
9781 result = mono_class_from_mono_type (inflated);
9782 mono_metadata_free_type (inflated);
9784 result = mono_class_from_mono_type (tb->type);
9786 *handle_class = mono_defaults.typehandle_class;
9788 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9789 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9790 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9791 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9792 result = ((MonoReflectionMethod*)obj)->method;
9793 result = mono_class_inflate_generic_method (result, context);
9794 *handle_class = mono_defaults.methodhandle_class;
9796 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9797 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9798 result = mb->mhandle;
9800 /* Type is not yet created */
9801 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9803 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9806 * Hopefully this has been filled in by calling CreateType() on the
9810 * TODO: This won't work if the application finishes another
9811 * TypeBuilder instance instead of this one.
9813 result = mb->mhandle;
9815 result = mono_class_inflate_generic_method (result, context);
9816 *handle_class = mono_defaults.methodhandle_class;
9817 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9818 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9820 result = cb->mhandle;
9822 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9824 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9825 result = cb->mhandle;
9827 result = mono_class_inflate_generic_method (result, context);
9828 *handle_class = mono_defaults.methodhandle_class;
9829 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9830 result = ((MonoReflectionField*)obj)->field;
9831 *handle_class = mono_defaults.fieldhandle_class;
9833 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9834 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9835 result = fb->handle;
9838 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9840 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9841 result = fb->handle;
9844 if (fb->handle && fb->handle->parent->generic_container) {
9845 MonoClass *klass = fb->handle->parent;
9846 MonoClass *inflated = mono_class_from_mono_type (mono_class_inflate_generic_type (&klass->byval_arg, context));
9848 result = mono_class_get_field_from_name (inflated, fb->handle->name);
9851 *handle_class = mono_defaults.fieldhandle_class;
9852 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9853 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9856 klass = tb->type.type->data.klass;
9857 if (klass->wastypebuilder) {
9858 /* Already created */
9862 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9863 result = tb->type.type->data.klass;
9866 *handle_class = mono_defaults.typehandle_class;
9867 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9868 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9869 MonoMethodSignature *sig;
9872 if (helper->arguments)
9873 nargs = mono_array_length (helper->arguments);
9877 sig = mono_metadata_signature_alloc (image, nargs);
9878 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9879 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9881 if (helper->call_conv == 0) /* unmanaged */
9882 sig->call_convention = helper->unmanaged_call_conv - 1;
9884 if (helper->call_conv & 0x02)
9885 sig->call_convention = MONO_CALL_VARARG;
9887 sig->call_convention = MONO_CALL_DEFAULT;
9889 sig->param_count = nargs;
9890 /* TODO: Copy type ? */
9891 sig->ret = helper->return_type->type;
9892 for (i = 0; i < nargs; ++i) {
9893 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9894 sig->params [i] = rt->type;
9898 *handle_class = NULL;
9899 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9900 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9901 /* Already created by the managed code */
9902 g_assert (method->mhandle);
9903 result = method->mhandle;
9904 *handle_class = mono_defaults.methodhandle_class;
9905 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
9906 MonoReflectionType *tb = (MonoReflectionType*)obj;
9907 result = mono_class_from_mono_type (mono_class_inflate_generic_type (tb->type, context));
9908 *handle_class = mono_defaults.typehandle_class;
9910 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
9911 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
9912 result = mono_class_from_mono_type (mono_class_inflate_generic_type (ref->type.type, context));
9913 *handle_class = mono_defaults.typehandle_class;
9916 g_print (obj->vtable->klass->name);
9917 g_assert_not_reached ();
9923 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9924 const static guint32 declsec_flags_map[] = {
9925 0x00000000, /* empty */
9926 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9927 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9928 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9929 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9930 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9931 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9932 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9933 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9934 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9935 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9936 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9937 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9938 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9939 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9940 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9941 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9942 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9943 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9947 * Returns flags that includes all available security action associated to the handle.
9948 * @token: metadata token (either for a class or a method)
9949 * @image: image where resides the metadata.
9952 mono_declsec_get_flags (MonoImage *image, guint32 token)
9954 int index = mono_metadata_declsec_from_index (image, token);
9955 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9960 /* HasSecurity can be present for other, not specially encoded, attributes,
9961 e.g. SuppressUnmanagedCodeSecurityAttribute */
9965 for (i = index; i < t->rows; i++) {
9966 guint32 cols [MONO_DECL_SECURITY_SIZE];
9968 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9969 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9972 action = cols [MONO_DECL_SECURITY_ACTION];
9973 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9974 result |= declsec_flags_map [action];
9976 g_assert_not_reached ();
9983 * Get the security actions (in the form of flags) associated with the specified method.
9985 * @method: The method for which we want the declarative security flags.
9986 * Return the declarative security flags for the method (only).
9988 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9989 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9992 mono_declsec_flags_from_method (MonoMethod *method)
9994 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9995 /* FIXME: No cache (for the moment) */
9996 guint32 idx = mono_method_get_index (method);
9997 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9998 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9999 return mono_declsec_get_flags (method->klass->image, idx);
10005 * Get the security actions (in the form of flags) associated with the specified class.
10007 * @klass: The class for which we want the declarative security flags.
10008 * Return the declarative security flags for the class.
10010 * Note: We cache the flags inside the MonoClass structure as this will get
10011 * called very often (at least for each method).
10014 mono_declsec_flags_from_class (MonoClass *klass)
10016 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10017 if (!klass->declsec_flags) {
10018 guint32 idx = mono_metadata_token_index (klass->type_token);
10019 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10020 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10021 /* we cache the flags on classes */
10022 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10024 return klass->declsec_flags;
10030 * Get the security actions (in the form of flags) associated with the specified assembly.
10032 * @assembly: The assembly for which we want the declarative security flags.
10033 * Return the declarative security flags for the assembly.
10036 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10038 guint32 idx = 1; /* there is only one assembly */
10039 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10040 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10041 return mono_declsec_get_flags (assembly->image, idx);
10046 * Fill actions for the specific index (which may either be an encoded class token or
10047 * an encoded method token) from the metadata image.
10048 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10051 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10052 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10054 MonoBoolean result = FALSE;
10056 guint32 cols [MONO_DECL_SECURITY_SIZE];
10057 int index = mono_metadata_declsec_from_index (image, token);
10060 t = &image->tables [MONO_TABLE_DECLSECURITY];
10061 for (i = index; i < t->rows; i++) {
10062 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10064 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10067 /* if present only replace (class) permissions with method permissions */
10068 /* if empty accept either class or method permissions */
10069 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10070 if (!actions->demand.blob) {
10071 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10072 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10073 actions->demand.blob = (char*) (blob + 2);
10074 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10077 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10078 if (!actions->noncasdemand.blob) {
10079 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10080 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10081 actions->noncasdemand.blob = (char*) (blob + 2);
10082 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10085 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10086 if (!actions->demandchoice.blob) {
10087 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10088 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10089 actions->demandchoice.blob = (char*) (blob + 2);
10090 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10100 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
10101 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10103 guint32 idx = mono_metadata_token_index (klass->type_token);
10104 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10105 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10106 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
10110 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
10111 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10113 guint32 idx = mono_method_get_index (method);
10114 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10115 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10116 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10120 * Collect all actions (that requires to generate code in mini) assigned for
10121 * the specified method.
10122 * Note: Don't use the content of actions if the function return FALSE.
10125 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10127 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
10128 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10129 MonoBoolean result = FALSE;
10132 /* quick exit if no declarative security is present in the metadata */
10133 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10136 /* we want the original as the wrapper is "free" of the security informations */
10137 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10138 method = mono_marshal_method_from_wrapper (method);
10143 /* First we look for method-level attributes */
10144 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10145 mono_class_init (method->klass);
10146 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10148 result = mono_declsec_get_method_demands_params (method, demands,
10149 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10152 /* Here we use (or create) the class declarative cache to look for demands */
10153 flags = mono_declsec_flags_from_class (method->klass);
10154 if (flags & mask) {
10156 mono_class_init (method->klass);
10157 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10159 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10160 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10163 /* The boolean return value is used as a shortcut in case nothing needs to
10164 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10170 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10172 * Note: Don't use the content of actions if the function return FALSE.
10175 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10177 MonoBoolean result = FALSE;
10180 /* quick exit if no declarative security is present in the metadata */
10181 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10184 /* we want the original as the wrapper is "free" of the security informations */
10185 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10186 method = mono_marshal_method_from_wrapper (method);
10191 /* results are independant - zeroize both */
10192 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10193 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10195 /* First we look for method-level attributes */
10196 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10197 mono_class_init (method->klass);
10199 result = mono_declsec_get_method_demands_params (method, cmethod,
10200 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10203 /* Here we use (or create) the class declarative cache to look for demands */
10204 flags = mono_declsec_flags_from_class (method->klass);
10205 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10206 mono_class_init (method->klass);
10208 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10209 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10216 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10218 * @klass The inherited class - this is the class that provides the security check (attributes)
10220 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10222 * Note: Don't use the content of actions if the function return FALSE.
10225 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10227 MonoBoolean result = FALSE;
10230 /* quick exit if no declarative security is present in the metadata */
10231 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10234 /* Here we use (or create) the class declarative cache to look for demands */
10235 flags = mono_declsec_flags_from_class (klass);
10236 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10237 mono_class_init (klass);
10238 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10240 result |= mono_declsec_get_class_demands_params (klass, demands,
10241 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10248 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10250 * Note: Don't use the content of actions if the function return FALSE.
10253 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10255 /* quick exit if no declarative security is present in the metadata */
10256 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10259 /* we want the original as the wrapper is "free" of the security informations */
10260 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10261 method = mono_marshal_method_from_wrapper (method);
10266 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10267 mono_class_init (method->klass);
10268 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10270 return mono_declsec_get_method_demands_params (method, demands,
10271 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10278 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10280 guint32 cols [MONO_DECL_SECURITY_SIZE];
10284 int index = mono_metadata_declsec_from_index (image, token);
10288 t = &image->tables [MONO_TABLE_DECLSECURITY];
10289 for (i = index; i < t->rows; i++) {
10290 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10292 /* shortcut - index are ordered */
10293 if (token != cols [MONO_DECL_SECURITY_PARENT])
10296 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10297 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10298 entry->blob = (char*) (metadata + 2);
10299 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10308 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10310 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10311 guint32 idx = mono_method_get_index (method);
10312 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10313 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10314 return get_declsec_action (method->klass->image, idx, action, entry);
10320 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10323 guint32 flags = mono_declsec_flags_from_class (klass);
10324 if (declsec_flags_map [action] & flags) {
10325 guint32 idx = mono_metadata_token_index (klass->type_token);
10326 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10327 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10328 return get_declsec_action (klass->image, idx, action, entry);
10334 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10336 guint32 idx = 1; /* there is only one assembly */
10337 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10338 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10340 return get_declsec_action (assembly->image, idx, action, entry);
10344 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10346 MonoObject *res, *exc;
10348 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10349 static MonoMethod *method = NULL;
10351 if (!System_Reflection_Emit_TypeBuilder) {
10352 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10353 g_assert (System_Reflection_Emit_TypeBuilder);
10355 if (method == NULL) {
10356 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10361 * The result of mono_type_get_object () might be a System.MonoType but we
10362 * need a TypeBuilder so use klass->reflection_info.
10364 g_assert (klass->reflection_info);
10365 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10367 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10369 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10373 return *(MonoBoolean*)mono_object_unbox (res);