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 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2432 MonoGenericClass *gclass;
2433 MonoDynamicGenericClass *dgclass;
2434 MonoReflectionFieldBuilder *fb = f->fb;
2437 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2440 klass = mono_class_from_mono_type (f->inst->type.type);
2441 gclass = f->inst->type.type->data.generic_class;
2442 g_assert (gclass->is_dynamic);
2443 dgclass = (MonoDynamicGenericClass *) gclass;
2445 // FIXME: Make the f objects unique, otherwise no use in caching their tokens
2446 name = mono_string_to_utf8 (fb->name);
2447 ftype = mono_class_inflate_generic_type (fb->type->type, mono_generic_class_get_context ((gclass)));
2448 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2449 fieldref_encode_signature (assembly, ftype));
2451 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2456 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2460 guint32 nparams = context->method_inst->type_argc;
2463 if (!assembly->save)
2466 sigbuffer_init (&buf, 32);
2468 * FIXME: vararg, explicit_this, differenc call_conv values...
2470 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2471 sigbuffer_add_value (&buf, nparams);
2473 for (i = 0; i < nparams; i++)
2474 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2476 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2477 sigbuffer_free (&buf);
2482 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2484 MonoDynamicTable *table;
2486 guint32 token, mtoken = 0, sig;
2487 MonoMethodInflated *imethod;
2488 MonoMethod *declaring;
2490 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2492 g_assert (method->is_inflated);
2493 imethod = (MonoMethodInflated *) method;
2494 declaring = imethod->declaring;
2496 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2497 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2499 if (!mono_method_signature (declaring)->generic_param_count)
2502 switch (mono_metadata_token_table (mtoken)) {
2503 case MONO_TABLE_MEMBERREF:
2504 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2506 case MONO_TABLE_METHOD:
2507 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2510 g_assert_not_reached ();
2513 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2515 if (assembly->save) {
2516 alloc_table (table, table->rows + 1);
2517 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2518 values [MONO_METHODSPEC_METHOD] = mtoken;
2519 values [MONO_METHODSPEC_SIGNATURE] = sig;
2522 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2529 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2531 MonoMethodInflated *imethod;
2534 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2538 g_assert (method->is_inflated);
2539 imethod = (MonoMethodInflated *) method;
2541 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2542 token = method_encode_methodspec (assembly, method);
2544 guint32 sig = method_encode_signature (
2545 assembly, mono_method_signature (imethod->declaring));
2546 token = mono_image_get_memberref_token (
2547 assembly, &method->klass->byval_arg, method->name, sig);
2550 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2555 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2557 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2560 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2561 token = mono_image_get_memberref_token (
2562 assembly, &m->klass->byval_arg, m->name, sig);
2568 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2570 MonoDynamicTable *table;
2578 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2579 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2580 * Because of this, we must not insert it into the `typeref' hash table.
2583 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2587 sigbuffer_init (&buf, 32);
2589 g_assert (tb->generic_params);
2590 klass = mono_class_from_mono_type (tb->type.type);
2592 if (tb->generic_container)
2593 mono_reflection_create_generic_class (tb);
2595 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2596 g_assert (klass->generic_container);
2597 sigbuffer_add_value (&buf, klass->byval_arg.type);
2598 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2600 count = mono_array_length (tb->generic_params);
2601 sigbuffer_add_value (&buf, count);
2602 for (i = 0; i < count; i++) {
2603 MonoReflectionGenericParam *gparam;
2605 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2607 encode_type (assembly, gparam->type.type, &buf);
2610 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2612 if (assembly->save) {
2613 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2614 alloc_table (table, table->rows + 1);
2615 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2616 values [MONO_TYPESPEC_SIGNATURE] = token;
2618 sigbuffer_free (&buf);
2620 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2621 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2627 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2629 MonoDynamicTable *table;
2632 guint32 token, pclass, parent, sig;
2635 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2639 klass = mono_class_from_mono_type (fb->typeb->type);
2640 name = mono_string_to_utf8 (fb->name);
2642 sig = fieldref_encode_signature (assembly, fb->type->type);
2644 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2645 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2647 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2648 parent >>= MONO_TYPEDEFORREF_BITS;
2650 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2652 if (assembly->save) {
2653 alloc_table (table, table->rows + 1);
2654 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2655 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2656 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2657 values [MONO_MEMBERREF_SIGNATURE] = sig;
2660 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2662 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2667 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2674 if (!assembly->save)
2677 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2678 g_assert (helper->type == 2);
2680 if (helper->arguments)
2681 nargs = mono_array_length (helper->arguments);
2685 size = 10 + (nargs * 10);
2687 sigbuffer_init (&buf, 32);
2689 /* Encode calling convention */
2690 /* Change Any to Standard */
2691 if ((helper->call_conv & 0x03) == 0x03)
2692 helper->call_conv = 0x01;
2693 /* explicit_this implies has_this */
2694 if (helper->call_conv & 0x40)
2695 helper->call_conv &= 0x20;
2697 if (helper->call_conv == 0) { /* Unmanaged */
2698 idx = helper->unmanaged_call_conv - 1;
2701 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2702 if (helper->call_conv & 0x02) /* varargs */
2706 sigbuffer_add_byte (&buf, idx);
2707 sigbuffer_add_value (&buf, nargs);
2708 encode_reflection_type (assembly, helper->return_type, &buf);
2709 for (i = 0; i < nargs; ++i) {
2710 MonoArray *modreqs = NULL;
2711 MonoArray *modopts = NULL;
2712 MonoReflectionType *pt;
2714 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
2715 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
2716 if (helper->modopts && (i < mono_array_length (helper->modopts)))
2717 modopts = mono_array_get (helper->modopts, MonoArray*, i);
2719 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
2720 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2721 encode_reflection_type (assembly, pt, &buf);
2723 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2724 sigbuffer_free (&buf);
2730 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2733 MonoDynamicTable *table;
2736 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2737 idx = table->next_idx ++;
2739 alloc_table (table, table->rows);
2740 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2742 values [MONO_STAND_ALONE_SIGNATURE] =
2743 mono_reflection_encode_sighelper (assembly, helper);
2749 reflection_cc_to_file (int call_conv) {
2750 switch (call_conv & 0x3) {
2752 case 1: return MONO_CALL_DEFAULT;
2753 case 2: return MONO_CALL_VARARG;
2755 g_assert_not_reached ();
2762 MonoMethodSignature *sig;
2768 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2773 MonoMethodSignature *sig;
2776 name = mono_string_to_utf8 (m->name);
2777 nparams = mono_array_length (m->parameters);
2778 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2780 sig->sentinelpos = -1;
2781 sig->call_convention = reflection_cc_to_file (m->call_conv);
2782 sig->param_count = nparams;
2783 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2784 for (i = 0; i < nparams; ++i) {
2785 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2786 sig->params [i] = t->type;
2789 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2791 if (strcmp (name, am->name) == 0 &&
2792 mono_metadata_type_equal (am->parent, m->parent->type) &&
2793 mono_metadata_signature_equal (am->sig, sig)) {
2796 m->table_idx = am->token & 0xffffff;
2800 am = g_new0 (ArrayMethod, 1);
2803 am->parent = m->parent->type;
2804 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2805 method_encode_signature (assembly, sig));
2806 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2807 m->table_idx = am->token & 0xffffff;
2812 * Insert into the metadata tables all the info about the TypeBuilder tb.
2813 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2816 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2818 MonoDynamicTable *table;
2820 int i, is_object = 0, is_system = 0;
2823 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2824 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2825 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2826 n = mono_string_to_utf8 (tb->name);
2827 if (strcmp (n, "Object") == 0)
2829 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2831 n = mono_string_to_utf8 (tb->nspace);
2832 if (strcmp (n, "System") == 0)
2834 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2836 if (tb->parent && !(is_system && is_object) &&
2837 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2838 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2840 values [MONO_TYPEDEF_EXTENDS] = 0;
2842 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2843 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2846 * if we have explicitlayout or sequentiallayouts, output data in the
2847 * ClassLayout table.
2849 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2850 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2851 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2853 alloc_table (table, table->rows);
2854 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2855 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2856 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2857 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2860 /* handle interfaces */
2861 if (tb->interfaces) {
2862 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2864 table->rows += mono_array_length (tb->interfaces);
2865 alloc_table (table, table->rows);
2866 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2867 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2868 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2869 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2870 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2871 values += MONO_INTERFACEIMPL_SIZE;
2877 table = &assembly->tables [MONO_TABLE_FIELD];
2878 table->rows += tb->num_fields;
2879 alloc_table (table, table->rows);
2880 for (i = 0; i < tb->num_fields; ++i)
2881 mono_image_get_field_info (
2882 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2885 /* handle constructors */
2887 table = &assembly->tables [MONO_TABLE_METHOD];
2888 table->rows += mono_array_length (tb->ctors);
2889 alloc_table (table, table->rows);
2890 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2891 mono_image_get_ctor_info (domain,
2892 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2895 /* handle methods */
2897 table = &assembly->tables [MONO_TABLE_METHOD];
2898 table->rows += tb->num_methods;
2899 alloc_table (table, table->rows);
2900 for (i = 0; i < tb->num_methods; ++i)
2901 mono_image_get_method_info (
2902 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2905 /* Do the same with properties etc.. */
2906 if (tb->events && mono_array_length (tb->events)) {
2907 table = &assembly->tables [MONO_TABLE_EVENT];
2908 table->rows += mono_array_length (tb->events);
2909 alloc_table (table, table->rows);
2910 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2912 alloc_table (table, table->rows);
2913 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2914 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2915 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2916 for (i = 0; i < mono_array_length (tb->events); ++i)
2917 mono_image_get_event_info (
2918 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2920 if (tb->properties && mono_array_length (tb->properties)) {
2921 table = &assembly->tables [MONO_TABLE_PROPERTY];
2922 table->rows += mono_array_length (tb->properties);
2923 alloc_table (table, table->rows);
2924 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2926 alloc_table (table, table->rows);
2927 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2928 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2929 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2930 for (i = 0; i < mono_array_length (tb->properties); ++i)
2931 mono_image_get_property_info (
2932 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2935 /* handle generic parameters */
2936 if (tb->generic_params) {
2937 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2938 table->rows += mono_array_length (tb->generic_params);
2939 alloc_table (table, table->rows);
2940 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2941 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2943 mono_image_get_generic_param_info (
2944 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2948 mono_image_add_decl_security (assembly,
2949 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2952 MonoDynamicTable *ntable;
2954 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2955 ntable->rows += mono_array_length (tb->subtypes);
2956 alloc_table (ntable, ntable->rows);
2957 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2959 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2960 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2962 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2963 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2964 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2965 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2966 mono_string_to_utf8 (tb->name), tb->table_idx,
2967 ntable->next_idx, ntable->rows);*/
2968 values += MONO_NESTED_CLASS_SIZE;
2975 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2979 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2981 if (!type->subtypes)
2984 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2985 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2986 collect_types (types, subtype);
2991 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2993 if ((*type1)->table_idx < (*type2)->table_idx)
2996 if ((*type1)->table_idx > (*type2)->table_idx)
3003 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3008 for (i = 0; i < mono_array_length (pinfo); ++i) {
3009 MonoReflectionParamBuilder *pb;
3010 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3013 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3018 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3021 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3023 for (i = 0; i < tb->num_fields; ++i) {
3024 MonoReflectionFieldBuilder* fb;
3025 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3026 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3030 for (i = 0; i < mono_array_length (tb->events); ++i) {
3031 MonoReflectionEventBuilder* eb;
3032 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3033 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3036 if (tb->properties) {
3037 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3038 MonoReflectionPropertyBuilder* pb;
3039 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3040 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3044 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3045 MonoReflectionCtorBuilder* cb;
3046 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3047 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3048 params_add_cattrs (assembly, cb->pinfo);
3053 for (i = 0; i < tb->num_methods; ++i) {
3054 MonoReflectionMethodBuilder* mb;
3055 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3056 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3057 params_add_cattrs (assembly, mb->pinfo);
3062 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3063 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3068 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3072 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3074 if (moduleb->global_methods) {
3075 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3076 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3077 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3078 params_add_cattrs (assembly, mb->pinfo);
3082 if (moduleb->global_fields) {
3083 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3084 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3085 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3089 if (moduleb->types) {
3090 for (i = 0; i < moduleb->num_types; ++i)
3091 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3096 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3098 MonoDynamicTable *table;
3102 char *b = blob_size;
3105 table = &assembly->tables [MONO_TABLE_FILE];
3107 alloc_table (table, table->rows);
3108 values = table->values + table->next_idx * MONO_FILE_SIZE;
3109 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3110 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3111 if (module->image->dynamic) {
3112 /* This depends on the fact that the main module is emitted last */
3113 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3114 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3117 path = g_strdup (module->image->name);
3119 mono_sha1_get_digest_from_file (path, hash);
3122 mono_metadata_encode_value (20, b, &b);
3123 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3124 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3129 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3131 MonoDynamicTable *table;
3134 table = &assembly->tables [MONO_TABLE_MODULE];
3135 mb->table_idx = table->next_idx ++;
3136 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3137 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3140 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3141 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3142 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3143 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3147 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3148 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3150 MonoDynamicTable *table;
3154 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3155 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3158 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3160 alloc_table (table, table->rows);
3161 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3163 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3164 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3165 if (klass->nested_in)
3166 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3168 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3169 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3170 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3172 res = table->next_idx;
3176 /* Emit nested types */
3177 if (klass->nested_classes) {
3180 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3181 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3188 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3189 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3194 klass = mono_class_from_mono_type (tb->type.type);
3196 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3198 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3199 parent_index, assembly);
3203 * We need to do this ourselves since klass->nested_classes is not set up.
3206 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3207 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3212 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3213 guint32 module_index, MonoDynamicImage *assembly)
3215 MonoImage *image = module->image;
3219 t = &image->tables [MONO_TABLE_TYPEDEF];
3221 for (i = 0; i < t->rows; ++i) {
3222 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3224 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3225 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3230 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3232 MonoDynamicTable *table;
3238 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3240 if (assemblyb->type_forwarders) {
3241 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3242 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3248 klass = mono_class_from_mono_type (t->type);
3250 scope = resolution_scope_from_image (assembly, klass->image);
3251 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3252 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3255 alloc_table (table, table->rows);
3256 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3258 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3259 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3260 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3261 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3262 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3267 #define align_pointer(base,p)\
3269 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3271 (p) += 4 - (__diff & 3);\
3275 compare_constants (const void *a, const void *b)
3277 const guint32 *a_values = a;
3278 const guint32 *b_values = b;
3279 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3283 compare_semantics (const void *a, const void *b)
3285 const guint32 *a_values = a;
3286 const guint32 *b_values = b;
3287 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3290 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3294 compare_custom_attrs (const void *a, const void *b)
3296 const guint32 *a_values = a;
3297 const guint32 *b_values = b;
3299 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3303 compare_field_marshal (const void *a, const void *b)
3305 const guint32 *a_values = a;
3306 const guint32 *b_values = b;
3308 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3312 compare_nested (const void *a, const void *b)
3314 const guint32 *a_values = a;
3315 const guint32 *b_values = b;
3317 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3321 compare_genericparam (const void *a, const void *b)
3323 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3324 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3326 if ((*b_entry)->owner == (*a_entry)->owner)
3328 (*a_entry)->gparam->type.type->data.generic_param->num -
3329 (*b_entry)->gparam->type.type->data.generic_param->num;
3331 return (*a_entry)->owner - (*b_entry)->owner;
3335 compare_declsecurity_attrs (const void *a, const void *b)
3337 const guint32 *a_values = a;
3338 const guint32 *b_values = b;
3340 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3344 pad_heap (MonoDynamicStream *sh)
3346 if (sh->index & 3) {
3347 int sz = 4 - (sh->index & 3);
3348 memset (sh->data + sh->index, 0, sz);
3355 MonoDynamicStream *stream;
3359 * build_compressed_metadata() fills in the blob of data that represents the
3360 * raw metadata as it will be saved in the PE file. The five streams are output
3361 * and the metadata tables are comnpressed from the guint32 array representation,
3362 * to the compressed on-disk format.
3365 build_compressed_metadata (MonoDynamicImage *assembly)
3367 MonoDynamicTable *table;
3369 guint64 valid_mask = 0;
3370 guint64 sorted_mask;
3371 guint32 heapt_size = 0;
3372 guint32 meta_size = 256; /* allow for header and other stuff */
3373 guint32 table_offset;
3374 guint32 ntables = 0;
3380 struct StreamDesc stream_desc [5];
3382 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3383 for (i = 0; i < assembly->gen_params->len; i++){
3384 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3385 write_generic_param_entry (assembly, entry);
3388 stream_desc [0].name = "#~";
3389 stream_desc [0].stream = &assembly->tstream;
3390 stream_desc [1].name = "#Strings";
3391 stream_desc [1].stream = &assembly->sheap;
3392 stream_desc [2].name = "#US";
3393 stream_desc [2].stream = &assembly->us;
3394 stream_desc [3].name = "#Blob";
3395 stream_desc [3].stream = &assembly->blob;
3396 stream_desc [4].name = "#GUID";
3397 stream_desc [4].stream = &assembly->guid;
3399 /* tables that are sorted */
3400 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3401 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3402 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3403 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3404 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3405 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3407 /* Compute table sizes */
3408 /* the MonoImage has already been created in mono_image_basic_init() */
3409 meta = &assembly->image;
3411 /* sizes should be multiple of 4 */
3412 pad_heap (&assembly->blob);
3413 pad_heap (&assembly->guid);
3414 pad_heap (&assembly->sheap);
3415 pad_heap (&assembly->us);
3417 /* Setup the info used by compute_sizes () */
3418 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3419 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3420 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3422 meta_size += assembly->blob.index;
3423 meta_size += assembly->guid.index;
3424 meta_size += assembly->sheap.index;
3425 meta_size += assembly->us.index;
3427 for (i=0; i < MONO_TABLE_NUM; ++i)
3428 meta->tables [i].rows = assembly->tables [i].rows;
3430 for (i = 0; i < MONO_TABLE_NUM; i++){
3431 if (meta->tables [i].rows == 0)
3433 valid_mask |= (guint64)1 << i;
3435 meta->tables [i].row_size = mono_metadata_compute_size (
3436 meta, i, &meta->tables [i].size_bitfield);
3437 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3439 heapt_size += 24; /* #~ header size */
3440 heapt_size += ntables * 4;
3441 /* make multiple of 4 */
3444 meta_size += heapt_size;
3445 meta->raw_metadata = g_malloc0 (meta_size);
3446 p = (unsigned char*)meta->raw_metadata;
3447 /* the metadata signature */
3448 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3449 /* version numbers and 4 bytes reserved */
3450 int16val = (guint16*)p;
3451 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3452 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3454 /* version string */
3455 int32val = (guint32*)p;
3456 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3458 memcpy (p, meta->version, strlen (meta->version));
3459 p += GUINT32_FROM_LE (*int32val);
3460 align_pointer (meta->raw_metadata, p);
3461 int16val = (guint16*)p;
3462 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3463 *int16val = GUINT16_TO_LE (5); /* number of streams */
3467 * write the stream info.
3469 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3470 table_offset += 3; table_offset &= ~3;
3472 assembly->tstream.index = heapt_size;
3473 for (i = 0; i < 5; ++i) {
3474 int32val = (guint32*)p;
3475 stream_desc [i].stream->offset = table_offset;
3476 *int32val++ = GUINT32_TO_LE (table_offset);
3477 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3478 table_offset += GUINT32_FROM_LE (*int32val);
3479 table_offset += 3; table_offset &= ~3;
3481 strcpy ((char*)p, stream_desc [i].name);
3482 p += strlen (stream_desc [i].name) + 1;
3483 align_pointer (meta->raw_metadata, p);
3486 * now copy the data, the table stream header and contents goes first.
3488 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3489 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3490 int32val = (guint32*)p;
3491 *int32val = GUINT32_TO_LE (0); /* reserved */
3494 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3495 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3496 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3497 *p++ = 2; /* version */
3500 *p++ = 1; /* version */
3504 if (meta->idx_string_wide)
3506 if (meta->idx_guid_wide)
3508 if (meta->idx_blob_wide)
3511 *p++ = 1; /* reserved */
3512 int64val = (guint64*)p;
3513 *int64val++ = GUINT64_TO_LE (valid_mask);
3514 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3516 int32val = (guint32*)p;
3517 for (i = 0; i < MONO_TABLE_NUM; i++){
3518 if (meta->tables [i].rows == 0)
3520 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3522 p = (unsigned char*)int32val;
3524 /* sort the tables that still need sorting */
3525 table = &assembly->tables [MONO_TABLE_CONSTANT];
3527 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3528 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3530 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3531 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3533 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3534 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3536 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3537 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3539 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3540 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3541 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3543 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3545 /* compress the tables */
3546 for (i = 0; i < MONO_TABLE_NUM; i++){
3549 guint32 bitfield = meta->tables [i].size_bitfield;
3550 if (!meta->tables [i].rows)
3552 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3553 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3554 meta->tables [i].base = (char*)p;
3555 for (row = 1; row <= meta->tables [i].rows; ++row) {
3556 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3557 for (col = 0; col < assembly->tables [i].columns; ++col) {
3558 switch (mono_metadata_table_size (bitfield, col)) {
3560 *p++ = values [col];
3563 *p++ = values [col] & 0xff;
3564 *p++ = (values [col] >> 8) & 0xff;
3567 *p++ = values [col] & 0xff;
3568 *p++ = (values [col] >> 8) & 0xff;
3569 *p++ = (values [col] >> 16) & 0xff;
3570 *p++ = (values [col] >> 24) & 0xff;
3573 g_assert_not_reached ();
3577 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3580 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3581 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3582 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3583 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3584 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3586 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3590 * Some tables in metadata need to be sorted according to some criteria, but
3591 * when methods and fields are first created with reflection, they may be assigned a token
3592 * that doesn't correspond to the final token they will get assigned after the sorting.
3593 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3594 * with the reflection objects that represent them. Once all the tables are set up, the
3595 * reflection objects will contains the correct table index. fixup_method() will fixup the
3596 * tokens for the method with ILGenerator @ilgen.
3599 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3600 guint32 code_idx = GPOINTER_TO_UINT (value);
3601 MonoReflectionILTokenInfo *iltoken;
3602 MonoReflectionFieldBuilder *field;
3603 MonoReflectionCtorBuilder *ctor;
3604 MonoReflectionMethodBuilder *method;
3605 MonoReflectionTypeBuilder *tb;
3606 MonoReflectionArrayMethod *am;
3608 unsigned char *target;
3610 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3611 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3612 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3613 switch (target [3]) {
3614 case MONO_TABLE_FIELD:
3615 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3616 field = (MonoReflectionFieldBuilder *)iltoken->member;
3617 idx = field->table_idx;
3618 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3619 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3620 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3622 g_assert_not_reached ();
3625 case MONO_TABLE_METHOD:
3626 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3627 method = (MonoReflectionMethodBuilder *)iltoken->member;
3628 idx = method->table_idx;
3629 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3630 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3631 idx = ctor->table_idx;
3632 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3633 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3634 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3635 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3637 g_assert_not_reached ();
3640 case MONO_TABLE_TYPEDEF:
3641 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3642 g_assert_not_reached ();
3643 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3644 idx = tb->table_idx;
3646 case MONO_TABLE_MEMBERREF:
3647 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3648 am = (MonoReflectionArrayMethod*)iltoken->member;
3649 idx = am->table_idx;
3650 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3651 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3652 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3653 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3654 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3655 g_assert (m->klass->generic_class || m->klass->generic_container);
3657 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3659 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3660 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3661 g_assert (f->generic_info);
3663 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3664 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3667 g_assert_not_reached ();
3670 case MONO_TABLE_METHODSPEC:
3671 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3672 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3673 g_assert (mono_method_signature (m)->generic_param_count);
3676 g_assert_not_reached ();
3680 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3682 target [0] = idx & 0xff;
3683 target [1] = (idx >> 8) & 0xff;
3684 target [2] = (idx >> 16) & 0xff;
3691 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3692 * value is not known when the table is emitted.
3695 fixup_cattrs (MonoDynamicImage *assembly)
3697 MonoDynamicTable *table;
3699 guint32 type, i, idx, token;
3702 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3704 for (i = 0; i < table->rows; ++i) {
3705 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3707 type = values [MONO_CUSTOM_ATTR_TYPE];
3708 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3709 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3710 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3711 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3714 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3715 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3716 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3717 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3724 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3726 MonoDynamicTable *table;
3729 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3731 alloc_table (table, table->rows);
3732 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3733 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3734 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3735 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3736 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3741 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3743 MonoDynamicTable *table;
3747 char *b = blob_size;
3749 guint32 idx, offset;
3751 if (rsrc->filename) {
3752 name = mono_string_to_utf8 (rsrc->filename);
3753 sname = g_path_get_basename (name);
3755 table = &assembly->tables [MONO_TABLE_FILE];
3757 alloc_table (table, table->rows);
3758 values = table->values + table->next_idx * MONO_FILE_SIZE;
3759 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3760 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3763 mono_sha1_get_digest_from_file (name, hash);
3764 mono_metadata_encode_value (20, b, &b);
3765 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3766 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3768 idx = table->next_idx++;
3770 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3776 data = mono_array_addr (rsrc->data, char, 0);
3777 len = mono_array_length (rsrc->data);
3783 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3784 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3785 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3786 mono_image_add_stream_data (&assembly->resources, data, len);
3790 * The entry should be emitted into the MANIFESTRESOURCE table of
3791 * the main module, but that needs to reference the FILE table
3792 * which isn't emitted yet.
3799 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3803 set_version_from_string (MonoString *version, guint32 *values)
3805 gchar *ver, *p, *str;
3808 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3809 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3810 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3811 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3814 ver = str = mono_string_to_utf8 (version);
3815 for (i = 0; i < 4; ++i) {
3816 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3822 /* handle Revision and Build */
3832 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3836 char *b = blob_size;
3841 len = mono_array_length (pkey);
3842 mono_metadata_encode_value (len, b, &b);
3843 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3844 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
3846 assembly->public_key = g_malloc (len);
3847 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
3848 assembly->public_key_len = len;
3850 /* Special case: check for ECMA key (16 bytes) */
3851 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
3852 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3853 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3854 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3855 /* minimum key size (in 2.0) is 384 bits */
3856 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3858 /* FIXME - verifier */
3859 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3860 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3862 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3868 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3870 MonoDynamicTable *table;
3871 MonoDynamicImage *assembly;
3872 MonoReflectionAssemblyBuilder *assemblyb;
3876 guint32 module_index;
3878 assemblyb = moduleb->assemblyb;
3879 assembly = moduleb->dynamic_image;
3880 domain = mono_object_domain (assemblyb);
3882 /* Emit ASSEMBLY table */
3883 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3884 alloc_table (table, 1);
3885 values = table->values + MONO_ASSEMBLY_SIZE;
3886 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3887 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3888 if (assemblyb->culture) {
3889 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3891 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3893 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3894 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3895 set_version_from_string (assemblyb->version, values);
3897 /* Emit FILE + EXPORTED_TYPE 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 if (file_module != moduleb) {
3904 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3906 if (file_module->types) {
3907 for (j = 0; j < file_module->num_types; ++j) {
3908 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3909 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3914 if (assemblyb->loaded_modules) {
3915 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3916 MonoReflectionModule *file_module =
3917 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3918 mono_image_fill_file_table (domain, file_module, assembly);
3920 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3923 if (assemblyb->type_forwarders)
3924 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3926 /* Emit MANIFESTRESOURCE table */
3928 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3930 MonoReflectionModuleBuilder *file_module =
3931 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3932 /* The table for the main module is emitted later */
3933 if (file_module != moduleb) {
3935 if (file_module->resources) {
3936 int len = mono_array_length (file_module->resources);
3937 for (j = 0; j < len; ++j) {
3938 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3939 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3947 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3948 * for the modulebuilder @moduleb.
3949 * At the end of the process, method and field tokens are fixed up and the
3950 * on-disk compressed metadata representation is created.
3953 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3955 MonoDynamicTable *table;
3956 MonoDynamicImage *assembly;
3957 MonoReflectionAssemblyBuilder *assemblyb;
3963 assemblyb = moduleb->assemblyb;
3964 assembly = moduleb->dynamic_image;
3965 domain = mono_object_domain (assemblyb);
3967 if (assembly->text_rva)
3970 assembly->text_rva = START_TEXT_RVA;
3972 if (moduleb->is_main) {
3973 mono_image_emit_manifest (moduleb);
3976 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3977 table->rows = 1; /* .<Module> */
3979 alloc_table (table, table->rows);
3981 * Set the first entry.
3983 values = table->values + table->columns;
3984 values [MONO_TYPEDEF_FLAGS] = 0;
3985 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3986 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3987 values [MONO_TYPEDEF_EXTENDS] = 0;
3988 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3989 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3992 * handle global methods
3993 * FIXME: test what to do when global methods are defined in multiple modules.
3995 if (moduleb->global_methods) {
3996 table = &assembly->tables [MONO_TABLE_METHOD];
3997 table->rows += mono_array_length (moduleb->global_methods);
3998 alloc_table (table, table->rows);
3999 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4000 mono_image_get_method_info (
4001 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4003 if (moduleb->global_fields) {
4004 table = &assembly->tables [MONO_TABLE_FIELD];
4005 table->rows += mono_array_length (moduleb->global_fields);
4006 alloc_table (table, table->rows);
4007 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4008 mono_image_get_field_info (
4009 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4012 table = &assembly->tables [MONO_TABLE_MODULE];
4013 alloc_table (table, 1);
4014 mono_image_fill_module_table (domain, moduleb, assembly);
4016 /* Collect all types into a list sorted by their table_idx */
4017 types = g_ptr_array_new ();
4020 for (i = 0; i < moduleb->num_types; ++i) {
4021 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4022 collect_types (types, type);
4025 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4026 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4027 table->rows += types->len;
4028 alloc_table (table, table->rows);
4031 * Emit type names + namespaces at one place inside the string heap,
4032 * so load_class_names () needs to touch fewer pages.
4034 for (i = 0; i < types->len; ++i) {
4035 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4036 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4038 for (i = 0; i < types->len; ++i) {
4039 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4040 string_heap_insert_mstring (&assembly->sheap, tb->name);
4043 for (i = 0; i < types->len; ++i) {
4044 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4045 mono_image_get_type_info (domain, type, assembly);
4049 * table->rows is already set above and in mono_image_fill_module_table.
4051 /* add all the custom attributes at the end, once all the indexes are stable */
4052 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4054 /* CAS assembly permissions */
4055 if (assemblyb->permissions_minimum)
4056 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4057 if (assemblyb->permissions_optional)
4058 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4059 if (assemblyb->permissions_refused)
4060 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4062 module_add_cattrs (assembly, moduleb);
4065 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4067 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4068 * the final tokens and don't need another fixup pass. */
4070 if (moduleb->global_methods) {
4071 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4072 MonoReflectionMethodBuilder *mb = mono_array_get (
4073 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4074 mono_image_add_methodimpl (assembly, mb);
4078 for (i = 0; i < types->len; ++i) {
4079 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4080 if (type->methods) {
4081 for (j = 0; j < type->num_methods; ++j) {
4082 MonoReflectionMethodBuilder *mb = mono_array_get (
4083 type->methods, MonoReflectionMethodBuilder*, j);
4085 mono_image_add_methodimpl (assembly, mb);
4090 g_ptr_array_free (types, TRUE);
4092 fixup_cattrs (assembly);
4096 * mono_image_insert_string:
4097 * @module: module builder object
4100 * Insert @str into the user string stream of @module.
4103 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4105 MonoDynamicImage *assembly;
4110 MONO_ARCH_SAVE_REGS;
4112 if (!module->dynamic_image)
4113 mono_image_module_basic_init (module);
4115 assembly = module->dynamic_image;
4117 if (assembly->save) {
4118 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4119 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4120 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4122 char *swapped = g_malloc (2 * mono_string_length (str));
4123 const char *p = (const char*)mono_string_chars (str);
4125 swap_with_size (swapped, p, 2, mono_string_length (str));
4126 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4130 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4132 mono_image_add_stream_data (&assembly->us, "", 1);
4134 idx = assembly->us.index ++;
4137 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4139 return MONO_TOKEN_STRING | idx;
4143 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4148 klass = obj->vtable->klass;
4149 if (strcmp (klass->name, "MonoMethod") == 0) {
4150 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4151 MonoMethodSignature *sig, *old;
4152 guint32 sig_token, parent;
4155 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4157 nargs = mono_array_length (opt_param_types);
4158 old = mono_method_signature (method);
4159 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4161 sig->hasthis = old->hasthis;
4162 sig->explicit_this = old->explicit_this;
4163 sig->call_convention = old->call_convention;
4164 sig->generic_param_count = old->generic_param_count;
4165 sig->param_count = old->param_count + nargs;
4166 sig->sentinelpos = old->param_count;
4167 sig->ret = old->ret;
4169 for (i = 0; i < old->param_count; i++)
4170 sig->params [i] = old->params [i];
4172 for (i = 0; i < nargs; i++) {
4173 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4174 sig->params [old->param_count + i] = rt->type;
4177 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4178 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4179 parent >>= MONO_TYPEDEFORREF_BITS;
4181 parent <<= MONO_MEMBERREF_PARENT_BITS;
4182 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4184 sig_token = method_encode_signature (assembly, sig);
4185 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4186 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4187 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4188 ReflectionMethodBuilder rmb;
4189 guint32 parent, sig;
4191 reflection_methodbuilder_from_method_builder (&rmb, mb);
4192 rmb.opt_types = opt_param_types;
4194 sig = method_builder_encode_signature (assembly, &rmb);
4196 parent = mono_image_create_token (assembly, obj, TRUE);
4197 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4199 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4200 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4202 token = mono_image_get_varargs_method_token (
4203 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4205 g_error ("requested method token for %s\n", klass->name);
4212 * mono_image_create_token:
4213 * @assembly: a dynamic assembly
4216 * Get a token to insert in the IL code stream for the given MemberInfo.
4217 * @obj can be one of:
4218 * ConstructorBuilder
4221 * GenericTypeParameterBuilder
4229 * MonoGenericCMethod
4235 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4240 klass = obj->vtable->klass;
4241 if (strcmp (klass->name, "MethodBuilder") == 0) {
4242 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4243 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4245 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4246 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4248 token = mono_image_get_methodbuilder_token (assembly, mb);
4249 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4250 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4251 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4252 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4254 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4255 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4257 token = mono_image_get_ctorbuilder_token (assembly, mb);
4258 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4259 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4260 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4261 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4262 if (tb->generic_params) {
4263 token = mono_image_get_generic_field_token (assembly, fb);
4265 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4267 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4268 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4269 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4270 } else if (strcmp (klass->name, "MonoType") == 0) {
4271 MonoReflectionType *tb = (MonoReflectionType *)obj;
4272 MonoClass *mc = mono_class_from_mono_type (tb->type);
4273 token = mono_metadata_token_from_dor (
4274 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4275 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4276 MonoReflectionType *tb = (MonoReflectionType *)obj;
4277 token = mono_metadata_token_from_dor (
4278 mono_image_typedef_or_ref (assembly, tb->type));
4279 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4280 MonoReflectionType *tb = (MonoReflectionType *)obj;
4281 token = mono_metadata_token_from_dor (
4282 mono_image_typedef_or_ref (assembly, tb->type));
4283 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4284 strcmp (klass->name, "MonoMethod") == 0 ||
4285 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4286 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4287 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4288 if (m->method->is_inflated) {
4289 if (create_methodspec)
4290 token = mono_image_get_methodspec_token (assembly, m->method);
4292 token = mono_image_get_inflated_method_token (assembly, m->method);
4293 } else if ((m->method->klass->image == &assembly->image) &&
4294 !m->method->klass->generic_class) {
4295 static guint32 method_table_idx = 0xffffff;
4296 if (m->method->klass->wastypebuilder) {
4297 /* we use the same token as the one that was assigned
4298 * to the Methodbuilder.
4299 * FIXME: do the equivalent for Fields.
4301 token = m->method->token;
4304 * Each token should have a unique index, but the indexes are
4305 * assigned by managed code, so we don't know about them. An
4306 * easy solution is to count backwards...
4308 method_table_idx --;
4309 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4312 token = mono_image_get_methodref_token (assembly, m->method);
4314 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4315 } else if (strcmp (klass->name, "MonoField") == 0) {
4316 MonoReflectionField *f = (MonoReflectionField *)obj;
4317 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4318 static guint32 field_table_idx = 0xffffff;
4320 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4322 token = mono_image_get_fieldref_token (assembly, f);
4324 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4325 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4326 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4327 token = mono_image_get_array_token (assembly, m);
4328 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4329 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4330 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4331 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4332 MonoReflectionType *tb = (MonoReflectionType *)obj;
4333 token = mono_metadata_token_from_dor (
4334 mono_image_typedef_or_ref (assembly, tb->type));
4335 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4336 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4337 token = mono_image_get_field_on_inst_token (assembly, f);
4339 g_error ("requested token for %s\n", klass->name);
4342 mono_image_register_token (assembly, token, obj);
4348 * mono_image_register_token:
4350 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY.
4353 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4355 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4359 guint32 import_lookup_table;
4363 guint32 import_address_table_rva;
4371 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4373 static MonoDynamicImage*
4374 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4376 static const guchar entrycode [16] = {0xff, 0x25, 0};
4377 MonoDynamicImage *image;
4380 const char *version = mono_get_runtime_info ()->runtime_version;
4383 image = GC_MALLOC (sizeof (MonoDynamicImage));
4385 image = g_new0 (MonoDynamicImage, 1);
4388 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4390 /*g_print ("created image %p\n", image);*/
4391 /* keep in sync with image.c */
4392 image->image.name = assembly_name;
4393 image->image.assembly_name = image->image.name; /* they may be different */
4394 image->image.module_name = module_name;
4395 image->image.version = g_strdup (version);
4396 image->image.md_version_major = 1;
4397 image->image.md_version_minor = 1;
4398 image->image.dynamic = TRUE;
4400 image->image.references = g_new0 (MonoAssembly*, 1);
4401 image->image.references [0] = NULL;
4403 mono_image_init (&image->image);
4405 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4406 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4407 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4408 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4409 image->handleref = g_hash_table_new (NULL, NULL);
4410 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4411 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4412 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4413 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4414 image->gen_params = g_ptr_array_new ();
4416 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4417 string_heap_init (&image->sheap);
4418 mono_image_add_stream_data (&image->us, "", 1);
4419 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4420 /* import tables... */
4421 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4422 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4423 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4424 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4425 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4426 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4427 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4428 stream_data_align (&image->code);
4430 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4432 for (i=0; i < MONO_TABLE_NUM; ++i) {
4433 image->tables [i].next_idx = 1;
4434 image->tables [i].columns = table_sizes [i];
4437 image->image.assembly = (MonoAssembly*)assembly;
4438 image->run = assembly->run;
4439 image->save = assembly->save;
4440 image->pe_kind = 0x1; /* ILOnly */
4441 image->machine = 0x14c; /* I386 */
4443 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4449 * mono_image_basic_init:
4450 * @assembly: an assembly builder object
4452 * Create the MonoImage that represents the assembly builder and setup some
4453 * of the helper hash table and the basic metadata streams.
4456 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4458 MonoDynamicAssembly *assembly;
4459 MonoDynamicImage *image;
4460 MonoDomain *domain = mono_object_domain (assemblyb);
4462 MONO_ARCH_SAVE_REGS;
4464 if (assemblyb->dynamic_assembly)
4468 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4470 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4473 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4475 assembly->assembly.ref_count = 1;
4476 assembly->assembly.dynamic = TRUE;
4477 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4478 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4479 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4480 if (assemblyb->culture)
4481 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4483 assembly->assembly.aname.culture = g_strdup ("");
4485 if (assemblyb->version) {
4486 char *vstr = mono_string_to_utf8 (assemblyb->version);
4487 char **version = g_strsplit (vstr, ".", 4);
4488 char **parts = version;
4489 assembly->assembly.aname.major = atoi (*parts++);
4490 assembly->assembly.aname.minor = atoi (*parts++);
4491 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4492 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4494 g_strfreev (version);
4497 assembly->assembly.aname.major = 0;
4498 assembly->assembly.aname.minor = 0;
4499 assembly->assembly.aname.build = 0;
4500 assembly->assembly.aname.revision = 0;
4503 assembly->run = assemblyb->access != 2;
4504 assembly->save = assemblyb->access != 1;
4506 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4507 image->initial_image = TRUE;
4508 assembly->assembly.aname.name = image->image.name;
4509 assembly->assembly.image = &image->image;
4511 mono_domain_assemblies_lock (domain);
4512 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4513 mono_domain_assemblies_unlock (domain);
4515 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4517 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4519 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4523 calc_section_size (MonoDynamicImage *assembly)
4527 /* alignment constraints */
4528 assembly->code.index += 3;
4529 assembly->code.index &= ~3;
4530 assembly->meta_size += 3;
4531 assembly->meta_size &= ~3;
4532 assembly->resources.index += 3;
4533 assembly->resources.index &= ~3;
4535 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4536 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4539 if (assembly->win32_res) {
4540 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4542 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4543 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4547 assembly->sections [MONO_SECTION_RELOC].size = 12;
4548 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4558 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4562 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4564 ResTreeNode *t1 = (ResTreeNode*)a;
4565 ResTreeNode *t2 = (ResTreeNode*)b;
4567 return t1->id - t2->id;
4571 * resource_tree_create:
4573 * Organize the resources into a resource tree.
4575 static ResTreeNode *
4576 resource_tree_create (MonoArray *win32_resources)
4578 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4582 tree = g_new0 (ResTreeNode, 1);
4584 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4585 MonoReflectionWin32Resource *win32_res =
4586 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4590 /* FIXME: BUG: this stores managed references in unmanaged memory */
4591 lang_node = g_new0 (ResTreeNode, 1);
4592 lang_node->id = win32_res->lang_id;
4593 lang_node->win32_res = win32_res;
4595 /* Create type node if neccesary */
4597 for (l = tree->children; l; l = l->next)
4598 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4599 type_node = (ResTreeNode*)l->data;
4604 type_node = g_new0 (ResTreeNode, 1);
4605 type_node->id = win32_res->res_type;
4608 * The resource types have to be sorted otherwise
4609 * Windows Explorer can't display the version information.
4611 tree->children = g_slist_insert_sorted (tree->children,
4612 type_node, resource_tree_compare_by_id);
4615 /* Create res node if neccesary */
4617 for (l = type_node->children; l; l = l->next)
4618 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4619 res_node = (ResTreeNode*)l->data;
4624 res_node = g_new0 (ResTreeNode, 1);
4625 res_node->id = win32_res->res_id;
4626 type_node->children = g_slist_append (type_node->children, res_node);
4629 res_node->children = g_slist_append (res_node->children, lang_node);
4636 * resource_tree_encode:
4638 * Encode the resource tree into the format used in the PE file.
4641 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4644 MonoPEResourceDir dir;
4645 MonoPEResourceDirEntry dir_entry;
4646 MonoPEResourceDataEntry data_entry;
4650 * For the format of the resource directory, see the article
4651 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4655 memset (&dir, 0, sizeof (dir));
4656 memset (&dir_entry, 0, sizeof (dir_entry));
4657 memset (&data_entry, 0, sizeof (data_entry));
4659 g_assert (sizeof (dir) == 16);
4660 g_assert (sizeof (dir_entry) == 8);
4661 g_assert (sizeof (data_entry) == 16);
4663 node->offset = p - begin;
4665 /* IMAGE_RESOURCE_DIRECTORY */
4666 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4668 memcpy (p, &dir, sizeof (dir));
4671 /* Reserve space for entries */
4673 p += sizeof (dir_entry) * dir.res_id_entries;
4675 /* Write children */
4676 for (l = node->children; l; l = l->next) {
4677 ResTreeNode *child = (ResTreeNode*)l->data;
4679 if (child->win32_res) {
4681 child->offset = p - begin;
4683 /* IMAGE_RESOURCE_DATA_ENTRY */
4684 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4685 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4687 memcpy (p, &data_entry, sizeof (data_entry));
4688 p += sizeof (data_entry);
4690 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4691 p += data_entry.rde_size;
4693 resource_tree_encode (child, begin, p, &p);
4697 /* IMAGE_RESOURCE_ENTRY */
4698 for (l = node->children; l; l = l->next) {
4699 ResTreeNode *child = (ResTreeNode*)l->data;
4700 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4702 dir_entry.is_dir = child->win32_res ? 0 : 1;
4703 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4705 memcpy (entries, &dir_entry, sizeof (dir_entry));
4706 entries += sizeof (dir_entry);
4713 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4718 MonoReflectionWin32Resource *win32_res;
4721 if (!assemblyb->win32_resources)
4725 * Resources are stored in a three level tree inside the PE file.
4726 * - level one contains a node for each type of resource
4727 * - level two contains a node for each resource
4728 * - level three contains a node for each instance of a resource for a
4729 * specific language.
4732 tree = resource_tree_create (assemblyb->win32_resources);
4734 /* Estimate the size of the encoded tree */
4736 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4737 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4738 size += mono_array_length (win32_res->res_data);
4740 /* Directory structure */
4741 size += mono_array_length (assemblyb->win32_resources) * 256;
4742 p = buf = g_malloc (size);
4744 resource_tree_encode (tree, p, p, &p);
4746 g_assert (p - buf <= size);
4748 assembly->win32_res = g_malloc (p - buf);
4749 assembly->win32_res_size = p - buf;
4750 memcpy (assembly->win32_res, buf, p - buf);
4756 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4758 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4761 p += sizeof (MonoPEResourceDir);
4762 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4763 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4764 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4765 if (dir_entry->is_dir) {
4766 fixup_resource_directory (res_section, child, rva);
4768 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4769 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4772 p += sizeof (MonoPEResourceDirEntry);
4777 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4780 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4781 g_error ("WriteFile returned %d\n", GetLastError ());
4785 * mono_image_create_pefile:
4786 * @mb: a module builder object
4788 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4789 * assembly->pefile where it can be easily retrieved later in chunks.
4792 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4793 MonoMSDOSHeader *msdos;
4794 MonoDotNetHeader *header;
4795 MonoSectionTable *section;
4796 MonoCLIHeader *cli_header;
4797 guint32 size, image_size, virtual_base, text_offset;
4798 guint32 header_start, section_start, file_offset, virtual_offset;
4799 MonoDynamicImage *assembly;
4800 MonoReflectionAssemblyBuilder *assemblyb;
4801 MonoDynamicStream pefile_stream = {0};
4802 MonoDynamicStream *pefile = &pefile_stream;
4804 guint32 *rva, value;
4806 static const unsigned char msheader[] = {
4807 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4808 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4809 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4810 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4811 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4812 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4813 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4814 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4817 assemblyb = mb->assemblyb;
4819 mono_image_basic_init (assemblyb);
4820 assembly = mb->dynamic_image;
4822 assembly->pe_kind = assemblyb->pe_kind;
4823 assembly->machine = assemblyb->machine;
4824 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4825 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4827 mono_image_build_metadata (mb);
4829 if (mb->is_main && assemblyb->resources) {
4830 int len = mono_array_length (assemblyb->resources);
4831 for (i = 0; i < len; ++i)
4832 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4835 if (mb->resources) {
4836 int len = mono_array_length (mb->resources);
4837 for (i = 0; i < len; ++i)
4838 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4841 build_compressed_metadata (assembly);
4844 assembly_add_win32_resources (assembly, assemblyb);
4846 nsections = calc_section_size (assembly);
4848 /* The DOS header and stub */
4849 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4850 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
4852 /* the dotnet header */
4853 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4855 /* the section tables */
4856 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4858 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4859 virtual_offset = VIRT_ALIGN;
4862 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4863 if (!assembly->sections [i].size)
4866 file_offset += FILE_ALIGN - 1;
4867 file_offset &= ~(FILE_ALIGN - 1);
4868 virtual_offset += VIRT_ALIGN - 1;
4869 virtual_offset &= ~(VIRT_ALIGN - 1);
4871 assembly->sections [i].offset = file_offset;
4872 assembly->sections [i].rva = virtual_offset;
4874 file_offset += assembly->sections [i].size;
4875 virtual_offset += assembly->sections [i].size;
4876 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4879 file_offset += FILE_ALIGN - 1;
4880 file_offset &= ~(FILE_ALIGN - 1);
4882 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4884 /* back-patch info */
4885 msdos = (MonoMSDOSHeader*)pefile->data;
4886 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4888 header = (MonoDotNetHeader*)(pefile->data + header_start);
4889 header->pesig [0] = 'P';
4890 header->pesig [1] = 'E';
4892 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4893 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4894 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4895 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4896 if (assemblyb->pekind == 1) {
4898 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4901 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4904 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4906 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4907 header->pe.pe_major = 6;
4908 header->pe.pe_minor = 0;
4909 size = assembly->sections [MONO_SECTION_TEXT].size;
4910 size += FILE_ALIGN - 1;
4911 size &= ~(FILE_ALIGN - 1);
4912 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4913 size = assembly->sections [MONO_SECTION_RSRC].size;
4914 size += FILE_ALIGN - 1;
4915 size &= ~(FILE_ALIGN - 1);
4916 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4917 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4918 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4919 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4920 /* pe_rva_entry_point always at the beginning of the text section */
4921 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4923 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4924 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4925 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4926 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4927 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4928 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4929 size = section_start;
4930 size += FILE_ALIGN - 1;
4931 size &= ~(FILE_ALIGN - 1);
4932 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4934 size += VIRT_ALIGN - 1;
4935 size &= ~(VIRT_ALIGN - 1);
4936 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4939 // Translate the PEFileKind value to the value expected by the Windows loader
4945 // PEFileKinds.Dll == 1
4946 // PEFileKinds.ConsoleApplication == 2
4947 // PEFileKinds.WindowApplication == 3
4950 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4951 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4953 if (assemblyb->pekind == 3)
4958 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4960 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4961 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4962 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4963 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4964 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4965 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4967 /* fill data directory entries */
4969 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4970 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4972 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4973 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4975 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4976 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4977 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4978 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4979 /* patch entrypoint name */
4980 if (assemblyb->pekind == 1)
4981 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4983 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4984 /* patch imported function RVA name */
4985 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4986 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4988 /* the import table */
4989 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4990 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4991 /* patch imported dll RVA name and other entries in the dir */
4992 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4993 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4994 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4995 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4996 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4997 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4999 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5000 value = (assembly->text_rva + assembly->imp_names_offset);
5001 *p++ = (value) & 0xff;
5002 *p++ = (value >> 8) & (0xff);
5003 *p++ = (value >> 16) & (0xff);
5004 *p++ = (value >> 24) & (0xff);
5006 /* the CLI header info */
5007 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5008 cli_header->ch_size = GUINT32_FROM_LE (72);
5009 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5010 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5011 if (assemblyb->entry_point) {
5012 guint32 table_idx = 0;
5013 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5014 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5015 table_idx = methodb->table_idx;
5017 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5019 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5021 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5023 /* The embedded managed resources */
5024 text_offset = assembly->text_rva + assembly->code.index;
5025 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5026 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5027 text_offset += assembly->resources.index;
5028 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5029 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5030 text_offset += assembly->meta_size;
5031 if (assembly->strong_name_size) {
5032 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5033 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5034 text_offset += assembly->strong_name_size;
5037 /* write the section tables and section content */
5038 section = (MonoSectionTable*)(pefile->data + section_start);
5039 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5040 static const char section_names [][7] = {
5041 ".text", ".rsrc", ".reloc"
5043 if (!assembly->sections [i].size)
5045 strcpy (section->st_name, section_names [i]);
5046 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5047 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5048 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5049 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5050 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5051 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5052 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5056 checked_write_file (file, pefile->data, pefile->index);
5058 mono_dynamic_stream_reset (pefile);
5060 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5061 if (!assembly->sections [i].size)
5064 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5065 g_error ("SetFilePointer returned %d\n", GetLastError ());
5068 case MONO_SECTION_TEXT:
5069 /* patch entry point */
5070 p = (guchar*)(assembly->code.data + 2);
5071 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5072 *p++ = (value) & 0xff;
5073 *p++ = (value >> 8) & 0xff;
5074 *p++ = (value >> 16) & 0xff;
5075 *p++ = (value >> 24) & 0xff;
5077 checked_write_file (file, assembly->code.data, assembly->code.index);
5078 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5079 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5080 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5083 g_free (assembly->image.raw_metadata);
5085 case MONO_SECTION_RELOC: {
5089 guint16 type_and_offset;
5093 g_assert (sizeof (reloc) == 12);
5095 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5096 reloc.block_size = GUINT32_FROM_LE (12);
5099 * the entrypoint is always at the start of the text section
5100 * 3 is IMAGE_REL_BASED_HIGHLOW
5101 * 2 is patch_size_rva - text_rva
5103 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5106 checked_write_file (file, &reloc, sizeof (reloc));
5110 case MONO_SECTION_RSRC:
5111 if (assembly->win32_res) {
5113 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5114 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5115 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5119 g_assert_not_reached ();
5123 /* check that the file is properly padded */
5124 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5125 g_error ("SetFilePointer returned %d\n", GetLastError ());
5126 if (! SetEndOfFile (file))
5127 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5129 mono_dynamic_stream_reset (&assembly->code);
5130 mono_dynamic_stream_reset (&assembly->us);
5131 mono_dynamic_stream_reset (&assembly->blob);
5132 mono_dynamic_stream_reset (&assembly->guid);
5133 mono_dynamic_stream_reset (&assembly->sheap);
5135 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5136 g_hash_table_destroy (assembly->blob_cache);
5137 assembly->blob_cache = NULL;
5140 MonoReflectionModule *
5141 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5145 MonoImageOpenStatus status;
5146 MonoDynamicAssembly *assembly;
5147 guint32 module_count;
5148 MonoImage **new_modules;
5149 gboolean *new_modules_loaded;
5151 name = mono_string_to_utf8 (fileName);
5153 image = mono_image_open (name, &status);
5156 if (status == MONO_IMAGE_ERROR_ERRNO)
5157 exc = mono_get_exception_file_not_found (fileName);
5159 exc = mono_get_exception_bad_image_format (name);
5161 mono_raise_exception (exc);
5166 assembly = ab->dynamic_assembly;
5167 image->assembly = (MonoAssembly*)assembly;
5169 module_count = image->assembly->image->module_count;
5170 new_modules = g_new0 (MonoImage *, module_count + 1);
5171 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5173 if (image->assembly->image->modules)
5174 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5175 if (image->assembly->image->modules_loaded)
5176 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5177 new_modules [module_count] = image;
5178 new_modules_loaded [module_count] = TRUE;
5179 mono_image_addref (image);
5181 g_free (image->assembly->image->modules);
5182 image->assembly->image->modules = new_modules;
5183 image->assembly->image->modules_loaded = new_modules_loaded;
5184 image->assembly->image->module_count ++;
5186 mono_assembly_load_references (image, &status);
5188 mono_image_close (image);
5189 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5192 return mono_module_get_object (mono_domain_get (), image);
5196 * We need to return always the same object for MethodInfo, FieldInfo etc..
5197 * but we need to consider the reflected type.
5198 * type uses a different hash, since it uses custom hash/equal functions.
5203 MonoClass *refclass;
5207 reflected_equal (gconstpointer a, gconstpointer b) {
5208 const ReflectedEntry *ea = a;
5209 const ReflectedEntry *eb = b;
5211 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5215 reflected_hash (gconstpointer a) {
5216 const ReflectedEntry *ea = a;
5217 return mono_aligned_addr_hash (ea->item);
5220 #define CHECK_OBJECT(t,p,k) \
5226 mono_domain_lock (domain); \
5227 if (!domain->refobject_hash) \
5228 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5229 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5230 mono_domain_unlock (domain); \
5233 mono_domain_unlock (domain); \
5236 #ifndef HAVE_NULL_GC
5237 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5239 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5242 #define CACHE_OBJECT(t,p,o,k) \
5245 ReflectedEntry pe; \
5247 pe.refclass = (k); \
5248 mono_domain_lock (domain); \
5249 if (!domain->refobject_hash) \
5250 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5251 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5253 ReflectedEntry *e = ALLOC_REFENTRY; \
5255 e->refclass = (k); \
5256 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5259 mono_domain_unlock (domain); \
5264 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5266 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5270 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5272 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5276 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5278 MonoDynamicImage *image = moduleb->dynamic_image;
5279 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5282 MonoImage **new_modules;
5285 * FIXME: we already created an image in mono_image_basic_init (), but
5286 * we don't know which module it belongs to, since that is only
5287 * determined at assembly save time.
5289 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5290 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5292 moduleb->module.image = &image->image;
5293 moduleb->dynamic_image = image;
5294 register_module (mono_object_domain (moduleb), moduleb, image);
5296 /* register the module with the assembly */
5297 ass = ab->dynamic_assembly->assembly.image;
5298 module_count = ass->module_count;
5299 new_modules = g_new0 (MonoImage *, module_count + 1);
5302 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5303 new_modules [module_count] = &image->image;
5304 mono_image_addref (&image->image);
5306 g_free (ass->modules);
5307 ass->modules = new_modules;
5308 ass->module_count ++;
5313 * mono_assembly_get_object:
5314 * @domain: an app domain
5315 * @assembly: an assembly
5317 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5319 MonoReflectionAssembly*
5320 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5322 static MonoClass *System_Reflection_Assembly;
5323 MonoReflectionAssembly *res;
5325 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5326 if (!System_Reflection_Assembly)
5327 System_Reflection_Assembly = mono_class_from_name (
5328 mono_defaults.corlib, "System.Reflection", "Assembly");
5329 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5330 res->assembly = assembly;
5332 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5337 MonoReflectionModule*
5338 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5340 static MonoClass *System_Reflection_Module;
5341 MonoReflectionModule *res;
5344 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
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);
5351 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5353 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5354 basename = g_path_get_basename (image->name);
5355 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5356 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5360 if (image->assembly->image == image) {
5361 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5365 if (image->assembly->image->modules) {
5366 for (i = 0; i < image->assembly->image->module_count; i++) {
5367 if (image->assembly->image->modules [i] == image)
5368 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5370 g_assert (res->token);
5374 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5377 MonoReflectionModule*
5378 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5380 static MonoClass *System_Reflection_Module;
5381 MonoReflectionModule *res;
5382 MonoTableInfo *table;
5383 guint32 cols [MONO_FILE_SIZE];
5385 guint32 i, name_idx;
5388 if (!System_Reflection_Module)
5389 System_Reflection_Module = mono_class_from_name (
5390 mono_defaults.corlib, "System.Reflection", "Module");
5391 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5393 table = &image->tables [MONO_TABLE_FILE];
5394 g_assert (table_index < table->rows);
5395 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5398 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5399 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5401 /* Check whenever the row has a corresponding row in the moduleref table */
5402 table = &image->tables [MONO_TABLE_MODULEREF];
5403 for (i = 0; i < table->rows; ++i) {
5404 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5405 val = mono_metadata_string_heap (image, name_idx);
5406 if (strcmp (val, name) == 0)
5407 res->image = image->modules [i];
5410 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5411 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5412 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5413 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5414 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5420 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5422 if ((t1->type != t2->type) ||
5423 (t1->byref != t2->byref))
5427 case MONO_TYPE_VOID:
5428 case MONO_TYPE_BOOLEAN:
5429 case MONO_TYPE_CHAR:
5440 case MONO_TYPE_STRING:
5443 case MONO_TYPE_OBJECT:
5444 case MONO_TYPE_TYPEDBYREF:
5446 case MONO_TYPE_VALUETYPE:
5447 case MONO_TYPE_CLASS:
5448 case MONO_TYPE_SZARRAY:
5449 return t1->data.klass == t2->data.klass;
5451 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5452 case MONO_TYPE_ARRAY:
5453 if (t1->data.array->rank != t2->data.array->rank)
5455 return t1->data.array->eklass == t2->data.array->eklass;
5456 case MONO_TYPE_GENERICINST: {
5458 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5459 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5460 if (i1->type_argc != i2->type_argc)
5462 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5463 &t2->data.generic_class->container_class->byval_arg))
5465 /* FIXME: we should probably just compare the instance pointers directly. */
5466 for (i = 0; i < i1->type_argc; ++i) {
5467 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5473 case MONO_TYPE_MVAR:
5474 return t1->data.generic_param == t2->data.generic_param;
5476 g_error ("implement type compare for %0x!", t1->type);
5484 mymono_metadata_type_hash (MonoType *t1)
5490 hash |= t1->byref << 6; /* do not collide with t1->type values */
5492 case MONO_TYPE_VALUETYPE:
5493 case MONO_TYPE_CLASS:
5494 case MONO_TYPE_SZARRAY:
5495 /* check if the distribution is good enough */
5496 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5498 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5499 case MONO_TYPE_GENERICINST: {
5501 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5502 hash += g_str_hash (t1->data.generic_class->container_class->name);
5504 for (i = 0; i < inst->type_argc; ++i) {
5505 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5514 static MonoReflectionGenericClass*
5515 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5517 static MonoClass *System_Reflection_MonoGenericClass;
5518 MonoReflectionGenericClass *res;
5519 MonoClass *klass, *gklass;
5521 if (!System_Reflection_MonoGenericClass) {
5522 System_Reflection_MonoGenericClass = mono_class_from_name (
5523 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5524 g_assert (System_Reflection_MonoGenericClass);
5527 klass = mono_class_from_mono_type (geninst);
5528 gklass = klass->generic_class->container_class;
5530 mono_class_init (klass);
5533 /* FIXME: allow unpinned later */
5534 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5536 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5539 res->type.type = geninst;
5540 g_assert (gklass->reflection_info);
5541 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
5542 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5548 verify_safe_for_managed_space (MonoType *type)
5550 switch (type->type) {
5552 case MONO_TYPE_ARRAY:
5553 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5555 return verify_safe_for_managed_space (type->data.type);
5556 case MONO_TYPE_SZARRAY:
5557 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5558 case MONO_TYPE_GENERICINST: {
5559 MonoGenericInst *inst = type->data.generic_class->inst;
5563 for (i = 0; i < inst->type_argc; ++i)
5564 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5570 case MONO_TYPE_MVAR:
5577 * mono_type_get_object:
5578 * @domain: an app domain
5581 * Return an System.MonoType object representing the type @type.
5584 mono_type_get_object (MonoDomain *domain, MonoType *type)
5586 MonoReflectionType *res;
5587 MonoClass *klass = mono_class_from_mono_type (type);
5589 mono_domain_lock (domain);
5590 if (!domain->type_hash)
5591 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5592 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5593 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5594 mono_domain_unlock (domain);
5597 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
5598 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
5599 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5600 mono_g_hash_table_insert (domain->type_hash, type, res);
5601 mono_domain_unlock (domain);
5605 if (!verify_safe_for_managed_space (type)) {
5606 mono_domain_unlock (domain);
5607 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5610 if (klass->reflection_info && !klass->wastypebuilder) {
5611 /* g_assert_not_reached (); */
5612 /* should this be considered an error condition? */
5614 mono_domain_unlock (domain);
5615 return klass->reflection_info;
5618 mono_class_init (klass);
5620 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5622 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5625 mono_g_hash_table_insert (domain->type_hash, type, res);
5626 mono_domain_unlock (domain);
5631 * mono_method_get_object:
5632 * @domain: an app domain
5634 * @refclass: the reflected type (can be NULL)
5636 * Return an System.Reflection.MonoMethod object representing the method @method.
5638 MonoReflectionMethod*
5639 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5642 * We use the same C representation for methods and constructors, but the type
5643 * name in C# is different.
5645 static MonoClass *System_Reflection_MonoMethod = NULL;
5646 static MonoClass *System_Reflection_MonoCMethod = NULL;
5647 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5648 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5650 MonoReflectionMethod *ret;
5652 if (method->is_inflated) {
5653 MonoReflectionGenericMethod *gret;
5655 refclass = method->klass;
5656 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5657 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5658 if (!System_Reflection_MonoGenericCMethod)
5659 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5660 klass = System_Reflection_MonoGenericCMethod;
5662 if (!System_Reflection_MonoGenericMethod)
5663 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5664 klass = System_Reflection_MonoGenericMethod;
5666 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5667 gret->method.method = method;
5668 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5669 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5670 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5674 refclass = method->klass;
5676 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5677 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5678 if (!System_Reflection_MonoCMethod)
5679 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5680 klass = System_Reflection_MonoCMethod;
5683 if (!System_Reflection_MonoMethod)
5684 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5685 klass = System_Reflection_MonoMethod;
5687 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5688 ret->method = method;
5689 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5690 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5694 * mono_field_get_object:
5695 * @domain: an app domain
5699 * Return an System.Reflection.MonoField object representing the field @field
5702 MonoReflectionField*
5703 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5705 MonoReflectionField *res;
5706 static MonoClass *monofield_klass;
5708 CHECK_OBJECT (MonoReflectionField *, field, klass);
5709 if (!monofield_klass)
5710 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5711 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
5714 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5715 if (field->generic_info)
5716 res->attrs = field->generic_info->generic_type->attrs;
5718 res->attrs = field->type->attrs;
5719 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5720 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5724 * mono_property_get_object:
5725 * @domain: an app domain
5727 * @property: a property
5729 * Return an System.Reflection.MonoProperty object representing the property @property
5732 MonoReflectionProperty*
5733 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5735 MonoReflectionProperty *res;
5736 static MonoClass *monoproperty_klass;
5738 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5739 if (!monoproperty_klass)
5740 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5741 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
5743 res->property = property;
5744 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5748 * mono_event_get_object:
5749 * @domain: an app domain
5753 * Return an System.Reflection.MonoEvent object representing the event @event
5756 MonoReflectionEvent*
5757 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5759 MonoReflectionEvent *res;
5760 static MonoClass *monoevent_klass;
5762 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5763 if (!monoevent_klass)
5764 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5765 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
5768 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5772 * mono_get_reflection_missing_object:
5773 * @domain: Domain where the object lives
5775 * Returns the System.Reflection.Missing.Value singleton object
5776 * (of type System.Reflection.Missing).
5778 * Used as the value for ParameterInfo.DefaultValue when Optional
5782 mono_get_reflection_missing_object (MonoDomain *domain)
5785 static MonoClassField *missing_value_field = NULL;
5787 if (!missing_value_field) {
5788 MonoClass *missing_klass;
5789 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
5790 mono_class_init (missing_klass);
5791 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
5792 g_assert (missing_value_field);
5794 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
5800 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
5803 *dbnull = mono_get_dbnull_object (domain);
5808 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
5810 if (!*reflection_missing)
5811 *reflection_missing = mono_get_reflection_missing_object (domain);
5812 return *reflection_missing;
5816 * mono_param_get_objects:
5817 * @domain: an app domain
5820 * Return an System.Reflection.ParameterInfo array object representing the parameters
5821 * in the method @method.
5824 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5826 static MonoClass *System_Reflection_ParameterInfo;
5827 MonoArray *res = NULL;
5828 MonoReflectionMethod *member = NULL;
5829 MonoReflectionParameter *param = NULL;
5830 char **names, **blobs = NULL;
5831 guint32 *types = NULL;
5832 MonoType *type = NULL;
5833 MonoObject *dbnull = NULL;
5834 MonoObject *missing = NULL;
5835 MonoMarshalSpec **mspecs;
5836 MonoMethodSignature *sig;
5839 if (!System_Reflection_ParameterInfo)
5840 System_Reflection_ParameterInfo = mono_class_from_name (
5841 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5843 if (!mono_method_signature (method)->param_count)
5844 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5846 /* Note: the cache is based on the address of the signature into the method
5847 * since we already cache MethodInfos with the method as keys.
5849 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5851 sig = mono_method_signature (method);
5852 member = mono_method_get_object (domain, method, NULL);
5853 names = g_new (char *, sig->param_count);
5854 mono_method_get_param_names (method, (const char **) names);
5856 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5857 mono_method_get_marshal_info (method, mspecs);
5859 res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5860 for (i = 0; i < sig->param_count; ++i) {
5861 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5862 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5863 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5864 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5865 param->PositionImpl = i;
5866 param->AttrsImpl = sig->params [i]->attrs;
5868 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5869 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
5870 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
5872 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
5876 blobs = g_new0 (char *, sig->param_count);
5877 types = g_new0 (guint32, sig->param_count);
5878 get_default_param_value_blobs (method, blobs, types);
5881 /* Build MonoType for the type from the Constant Table */
5883 type = g_new0 (MonoType, 1);
5884 type->type = types [i];
5885 type->data.klass = NULL;
5886 if (types [i] == MONO_TYPE_CLASS)
5887 type->data.klass = mono_defaults.object_class;
5888 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5889 /* For enums, types [i] contains the base type */
5891 type->type = MONO_TYPE_VALUETYPE;
5892 type->data.klass = mono_class_from_mono_type (sig->params [i]);
5894 type->data.klass = mono_class_from_mono_type (type);
5896 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5898 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5899 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
5900 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
5901 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
5903 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
5909 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5911 mono_array_setref (res, i, param);
5918 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5920 mono_metadata_free_marshal_spec (mspecs [i]);
5923 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5927 * mono_method_body_get_object:
5928 * @domain: an app domain
5931 * Return an System.Reflection.MethodBody object representing the method @method.
5933 MonoReflectionMethodBody*
5934 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5936 static MonoClass *System_Reflection_MethodBody = NULL;
5937 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5938 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5939 MonoReflectionMethodBody *ret;
5940 MonoMethodNormal *mn;
5941 MonoMethodHeader *header;
5942 guint32 method_rva, local_var_sig_token;
5944 unsigned char format, flags;
5947 if (!System_Reflection_MethodBody)
5948 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5949 if (!System_Reflection_LocalVariableInfo)
5950 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5951 if (!System_Reflection_ExceptionHandlingClause)
5952 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5954 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5956 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5957 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5958 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5959 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5961 mn = (MonoMethodNormal *)method;
5962 header = mono_method_get_header (method);
5964 /* Obtain local vars signature token */
5965 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5966 ptr = mono_image_rva_map (method->klass->image, method_rva);
5967 flags = *(const unsigned char *) ptr;
5968 format = flags & METHOD_HEADER_FORMAT_MASK;
5970 case METHOD_HEADER_TINY_FORMAT:
5971 case METHOD_HEADER_TINY_FORMAT1:
5972 local_var_sig_token = 0;
5974 case METHOD_HEADER_FAT_FORMAT:
5978 local_var_sig_token = read32 (ptr);
5981 g_assert_not_reached ();
5984 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5986 ret->init_locals = header->init_locals;
5987 ret->max_stack = header->max_stack;
5988 ret->local_var_sig_token = local_var_sig_token;
5989 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5990 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5993 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5994 for (i = 0; i < header->num_locals; ++i) {
5995 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5996 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5997 info->is_pinned = header->locals [i]->pinned;
5998 info->local_index = i;
5999 mono_array_setref (ret->locals, i, info);
6003 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6004 for (i = 0; i < header->num_clauses; ++i) {
6005 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6006 MonoExceptionClause *clause = &header->clauses [i];
6008 info->flags = clause->flags;
6009 info->try_offset = clause->try_offset;
6010 info->try_length = clause->try_len;
6011 info->handler_offset = clause->handler_offset;
6012 info->handler_length = clause->handler_len;
6013 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6014 info->filter_offset = clause->data.filter_offset;
6015 else if (clause->data.catch_class)
6016 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6018 mono_array_setref (ret->clauses, i, info);
6021 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6026 * mono_get_dbnull_object:
6027 * @domain: Domain where the object lives
6029 * Returns the System.DBNull.Value singleton object
6031 * Used as the value for ParameterInfo.DefaultValue
6034 mono_get_dbnull_object (MonoDomain *domain)
6037 static MonoClassField *dbnull_value_field = NULL;
6039 if (!dbnull_value_field) {
6040 MonoClass *dbnull_klass;
6041 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6042 mono_class_init (dbnull_klass);
6043 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6044 g_assert (dbnull_value_field);
6046 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6052 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6054 guint32 param_index, i, lastp, crow = 0;
6055 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6058 MonoClass *klass = method->klass;
6059 MonoImage *image = klass->image;
6060 MonoMethodSignature *methodsig = mono_method_signature (method);
6062 MonoTableInfo *constt;
6063 MonoTableInfo *methodt;
6064 MonoTableInfo *paramt;
6066 if (!methodsig->param_count)
6069 mono_class_init (klass);
6071 if (klass->image->dynamic) {
6072 MonoReflectionMethodAux *aux;
6073 if (method->is_inflated)
6074 method = ((MonoMethodInflated*)method)->declaring;
6075 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6076 if (aux && aux->param_defaults) {
6077 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6078 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6083 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6084 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6085 constt = &image->tables [MONO_TABLE_CONSTANT];
6087 idx = mono_method_get_index (method) - 1;
6088 g_assert (idx != -1);
6090 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6091 if (idx + 1 < methodt->rows)
6092 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6094 lastp = paramt->rows + 1;
6096 for (i = param_index; i < lastp; ++i) {
6099 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6100 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6102 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6105 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6110 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6111 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6112 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6119 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6124 MonoType *basetype = type;
6129 klass = mono_class_from_mono_type (type);
6130 if (klass->valuetype) {
6131 object = mono_object_new (domain, klass);
6132 retval = ((gchar *) object + sizeof (MonoObject));
6133 if (klass->enumtype)
6134 basetype = klass->enum_basetype;
6139 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6146 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6150 memset (assembly, 0, sizeof (MonoAssemblyName));
6152 assembly->culture = "";
6153 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6155 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6158 while (g_ascii_isspace (*p) || *p == ',') {
6167 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6169 assembly->major = strtoul (p, &s, 10);
6170 if (s == p || *s != '.')
6173 assembly->minor = strtoul (p, &s, 10);
6174 if (s == p || *s != '.')
6177 assembly->build = strtoul (p, &s, 10);
6178 if (s == p || *s != '.')
6181 assembly->revision = strtoul (p, &s, 10);
6185 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6187 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6188 assembly->culture = "";
6191 assembly->culture = p;
6192 while (*p && *p != ',') {
6196 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6198 if (strncmp (p, "null", 4) == 0) {
6203 while (*p && *p != ',') {
6206 len = (p - start + 1);
6207 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6208 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6209 g_strlcpy ((char*)assembly->public_key_token, start, len);
6212 while (*p && *p != ',')
6216 while (g_ascii_isspace (*p) || *p == ',') {
6230 * mono_reflection_parse_type:
6233 * Parse a type name as accepted by the GetType () method and output the info
6234 * extracted in the info structure.
6235 * the name param will be mangled, so, make a copy before passing it to this function.
6236 * The fields in info will be valid until the memory pointed to by name is valid.
6238 * See also mono_type_get_name () below.
6240 * Returns: 0 on parse error.
6243 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6244 MonoTypeNameParse *info)
6246 char *start, *p, *w, *temp, *last_point, *startn;
6247 int in_modifiers = 0;
6248 int isbyref = 0, rank, arity = 0, i;
6250 start = p = w = name;
6252 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6253 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6254 info->name = info->name_space = NULL;
6255 info->nested = NULL;
6256 info->modifiers = NULL;
6257 info->type_arguments = NULL;
6259 /* last_point separates the namespace from the name */
6265 *p = 0; /* NULL terminate the name */
6267 info->nested = g_list_append (info->nested, startn);
6268 /* we have parsed the nesting namespace + name */
6272 info->name_space = start;
6274 info->name = last_point + 1;
6276 info->name_space = (char *)"";
6295 i = strtol (p, &temp, 10);
6312 info->name_space = start;
6314 info->name = last_point + 1;
6316 info->name_space = (char *)"";
6323 if (isbyref) /* only one level allowed by the spec */
6326 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6330 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6336 info->type_arguments = g_ptr_array_new ();
6337 for (i = 0; i < arity; i++) {
6338 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6339 gboolean fqname = FALSE;
6341 g_ptr_array_add (info->type_arguments, subinfo);
6348 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6359 while (*p && (*p != ']'))
6367 if (g_ascii_isspace (*aname)) {
6374 !assembly_name_to_aname (&subinfo->assembly, aname))
6378 if (i + 1 < arity) {
6398 else if (*p == '*') /* '*' means unknown lower bound */
6399 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6406 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6417 if (g_ascii_isspace (*p)) {
6424 return 0; /* missing assembly name */
6425 if (!assembly_name_to_aname (&info->assembly, p))
6431 if (info->assembly.name)
6434 // *w = 0; /* terminate class name */
6436 if (!info->name || !*info->name)
6440 /* add other consistency checks */
6445 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6447 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6451 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6453 gboolean type_resolve = FALSE;
6455 MonoImage *rootimage = image;
6457 if (info->assembly.name) {
6458 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6460 /* then we must load the assembly ourselve - see #60439 */
6461 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6465 image = assembly->image;
6466 } else if (!image) {
6467 image = mono_defaults.corlib;
6470 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6471 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6472 image = mono_defaults.corlib;
6473 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6480 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6485 gboolean bounded = FALSE;
6488 image = mono_defaults.corlib;
6491 klass = mono_class_from_name_case (image, info->name_space, info->name);
6493 klass = mono_class_from_name (image, info->name_space, info->name);
6496 for (mod = info->nested; mod; mod = mod->next) {
6499 mono_class_init (klass);
6500 nested = klass->nested_classes;
6503 klass = nested->data;
6505 if (g_strcasecmp (klass->name, mod->data) == 0)
6508 if (strcmp (klass->name, mod->data) == 0)
6512 nested = nested->next;
6519 mono_class_init (klass);
6521 if (info->type_arguments) {
6522 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6523 MonoReflectionType *the_type;
6527 for (i = 0; i < info->type_arguments->len; i++) {
6528 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6530 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
6531 if (!type_args [i]) {
6537 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6539 instance = mono_reflection_bind_generic_parameters (
6540 the_type, info->type_arguments->len, type_args);
6546 klass = mono_class_from_mono_type (instance);
6549 for (mod = info->modifiers; mod; mod = mod->next) {
6550 modval = GPOINTER_TO_UINT (mod->data);
6551 if (!modval) { /* byref: must be last modifier */
6552 return &klass->this_arg;
6553 } else if (modval == -1) {
6554 klass = mono_ptr_class_get (&klass->byval_arg);
6555 } else if (modval == -2) {
6557 } else { /* array rank */
6558 klass = mono_bounded_array_class_get (klass, modval, bounded);
6560 mono_class_init (klass);
6563 return &klass->byval_arg;
6567 * mono_reflection_get_type:
6568 * @image: a metadata context
6569 * @info: type description structure
6570 * @ignorecase: flag for case-insensitive string compares
6571 * @type_resolve: whenever type resolve was already tried
6573 * Build a MonoType from the type description in @info.
6578 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
6579 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
6583 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
6585 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
6589 g_assert (assembly->dynamic);
6591 /* Enumerate all modules */
6594 if (abuilder->modules) {
6595 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6596 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6597 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
6603 if (!type && abuilder->loaded_modules) {
6604 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6605 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6606 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
6616 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6619 MonoReflectionAssembly *assembly;
6623 if (image && image->dynamic)
6624 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
6626 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
6629 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6636 *type_resolve = TRUE;
6639 /* Reconstruct the type name */
6640 fullName = g_string_new ("");
6641 if (info->name_space && (info->name_space [0] != '\0'))
6642 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6644 g_string_printf (fullName, info->name);
6645 for (mod = info->nested; mod; mod = mod->next)
6646 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6648 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6650 if (assembly->assembly->dynamic)
6651 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
6653 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
6656 g_string_free (fullName, TRUE);
6661 mono_reflection_free_type_info (MonoTypeNameParse *info)
6663 g_list_free (info->modifiers);
6664 g_list_free (info->nested);
6666 if (info->type_arguments) {
6669 for (i = 0; i < info->type_arguments->len; i++) {
6670 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6672 mono_reflection_free_type_info (subinfo);
6673 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
6677 g_ptr_array_free (info->type_arguments, TRUE);
6682 * mono_reflection_type_from_name:
6684 * @image: a metadata context (can be NULL).
6686 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6687 * it defaults to get the type from @image or, if @image is NULL or loading
6688 * from it fails, uses corlib.
6692 mono_reflection_type_from_name (char *name, MonoImage *image)
6694 MonoType *type = NULL;
6695 MonoTypeNameParse info;
6698 /* Make a copy since parse_type modifies its argument */
6699 tmp = g_strdup (name);
6701 /*g_print ("requested type %s\n", str);*/
6702 if (mono_reflection_parse_type (tmp, &info)) {
6703 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6707 mono_reflection_free_type_info (&info);
6712 * mono_reflection_get_token:
6714 * Return the metadata token of OBJ which should be an object
6715 * representing a metadata element.
6718 mono_reflection_get_token (MonoObject *obj)
6723 klass = obj->vtable->klass;
6725 if (strcmp (klass->name, "MethodBuilder") == 0) {
6726 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6728 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6729 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6730 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6732 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6733 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6734 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6736 /* Call mono_image_create_token so the object gets added to the tokens hash table */
6737 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE);
6738 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6739 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6740 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6741 } else if (strcmp (klass->name, "MonoType") == 0) {
6742 MonoReflectionType *tb = (MonoReflectionType *)obj;
6743 token = mono_class_from_mono_type (tb->type)->type_token;
6744 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6745 strcmp (klass->name, "MonoMethod") == 0 ||
6746 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6747 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6748 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6749 if (m->method->is_inflated) {
6750 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6751 return inflated->declaring->token;
6753 token = m->method->token;
6755 } else if (strcmp (klass->name, "MonoField") == 0) {
6756 MonoReflectionField *f = (MonoReflectionField*)obj;
6758 if (f->field->generic_info && f->field->generic_info->reflection_info)
6759 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6761 token = mono_class_get_field_token (f->field);
6762 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6763 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6765 token = mono_class_get_property_token (p->property);
6766 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6767 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6769 token = mono_class_get_event_token (p->event);
6770 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6771 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6773 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6774 } else if (strcmp (klass->name, "Module") == 0) {
6775 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6778 } else if (strcmp (klass->name, "Assembly") == 0) {
6779 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6781 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6782 MonoException *ex = mono_get_exception_not_implemented (msg);
6784 mono_raise_exception (ex);
6791 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6793 int slen, type = t->type;
6794 MonoClass *tklass = t->data.klass;
6800 case MONO_TYPE_BOOLEAN: {
6801 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6806 case MONO_TYPE_CHAR:
6808 case MONO_TYPE_I2: {
6809 guint16 *val = g_malloc (sizeof (guint16));
6814 #if SIZEOF_VOID_P == 4
6820 case MONO_TYPE_I4: {
6821 guint32 *val = g_malloc (sizeof (guint32));
6826 #if SIZEOF_VOID_P == 8
6827 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6831 case MONO_TYPE_I8: {
6832 guint64 *val = g_malloc (sizeof (guint64));
6837 case MONO_TYPE_R8: {
6838 double *val = g_malloc (sizeof (double));
6843 case MONO_TYPE_VALUETYPE:
6844 if (t->data.klass->enumtype) {
6845 type = t->data.klass->enum_basetype->type;
6848 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6851 case MONO_TYPE_STRING:
6852 if (*p == (char)0xFF) {
6856 slen = mono_metadata_decode_value (p, &p);
6858 return mono_string_new_len (mono_domain_get (), p, slen);
6859 case MONO_TYPE_CLASS: {
6862 if (*p == (char)0xFF) {
6867 slen = mono_metadata_decode_value (p, &p);
6868 n = g_memdup (p, slen + 1);
6870 t = mono_reflection_type_from_name (n, image);
6872 g_warning ("Cannot load type '%s'", n);
6876 return mono_type_get_object (mono_domain_get (), t);
6880 case MONO_TYPE_OBJECT: {
6883 MonoClass *subc = NULL;
6888 } else if (subt == 0x0E) {
6889 type = MONO_TYPE_STRING;
6891 } else if (subt == 0x1D) {
6892 MonoType simple_type = {{0}};
6897 /* See Partition II, Appendix B3 */
6898 etype = MONO_TYPE_OBJECT;
6899 type = MONO_TYPE_SZARRAY;
6900 simple_type.type = etype;
6901 tklass = mono_class_from_mono_type (&simple_type);
6903 } else if (subt == 0x55) {
6906 slen = mono_metadata_decode_value (p, &p);
6907 n = g_memdup (p, slen + 1);
6909 t = mono_reflection_type_from_name (n, image);
6911 g_error ("Cannot load type '%s'", n);
6914 subc = mono_class_from_mono_type (t);
6915 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6916 MonoType simple_type = {{0}};
6917 simple_type.type = subt;
6918 subc = mono_class_from_mono_type (&simple_type);
6920 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6922 val = load_cattr_value (image, &subc->byval_arg, p, end);
6923 obj = mono_object_new (mono_domain_get (), subc);
6924 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6928 case MONO_TYPE_SZARRAY: {
6930 guint32 i, alen, basetype;
6933 if (alen == 0xffffffff) {
6937 arr = mono_array_new (mono_domain_get(), tklass, alen);
6938 basetype = tklass->byval_arg.type;
6939 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
6940 basetype = tklass->enum_basetype->type;
6945 case MONO_TYPE_BOOLEAN:
6946 for (i = 0; i < alen; i++) {
6947 MonoBoolean val = *p++;
6948 mono_array_set (arr, MonoBoolean, i, val);
6951 case MONO_TYPE_CHAR:
6954 for (i = 0; i < alen; i++) {
6955 guint16 val = read16 (p);
6956 mono_array_set (arr, guint16, i, val);
6963 for (i = 0; i < alen; i++) {
6964 guint32 val = read32 (p);
6965 mono_array_set (arr, guint32, i, val);
6970 for (i = 0; i < alen; i++) {
6973 mono_array_set (arr, double, i, val);
6979 for (i = 0; i < alen; i++) {
6980 guint64 val = read64 (p);
6981 mono_array_set (arr, guint64, i, val);
6985 case MONO_TYPE_CLASS:
6986 case MONO_TYPE_OBJECT:
6987 case MONO_TYPE_STRING:
6988 for (i = 0; i < alen; i++) {
6989 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6990 mono_array_setref (arr, i, item);
6994 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7000 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7006 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7008 static MonoClass *klass;
7009 static MonoMethod *ctor;
7011 void *params [2], *unboxed;
7014 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7016 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7018 params [0] = mono_type_get_object (mono_domain_get (), t);
7020 retval = mono_object_new (mono_domain_get (), klass);
7021 unboxed = mono_object_unbox (retval);
7022 mono_runtime_invoke (ctor, unboxed, params, NULL);
7028 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7030 static MonoClass *klass;
7031 static MonoMethod *ctor;
7033 void *unboxed, *params [2];
7036 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7038 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7041 params [1] = typedarg;
7042 retval = mono_object_new (mono_domain_get (), klass);
7043 unboxed = mono_object_unbox (retval);
7044 mono_runtime_invoke (ctor, unboxed, params, NULL);
7050 type_is_reference (MonoType *type)
7052 switch (type->type) {
7053 case MONO_TYPE_BOOLEAN:
7054 case MONO_TYPE_CHAR:
7067 case MONO_TYPE_VALUETYPE:
7075 free_param_data (MonoMethodSignature *sig, void **params) {
7077 for (i = 0; i < sig->param_count; ++i) {
7078 if (!type_is_reference (sig->params [i]))
7079 g_free (params [i]);
7084 * Find the field index in the metadata FieldDef table.
7087 find_field_index (MonoClass *klass, MonoClassField *field) {
7090 for (i = 0; i < klass->field.count; ++i) {
7091 if (field == &klass->fields [i])
7092 return klass->field.first + 1 + i;
7098 * Find the property index in the metadata Property table.
7101 find_property_index (MonoClass *klass, MonoProperty *property) {
7104 for (i = 0; i < klass->property.count; ++i) {
7105 if (property == &klass->properties [i])
7106 return klass->property.first + 1 + i;
7112 * Find the event index in the metadata Event table.
7115 find_event_index (MonoClass *klass, MonoEvent *event) {
7118 for (i = 0; i < klass->event.count; ++i) {
7119 if (event == &klass->events [i])
7120 return klass->event.first + 1 + i;
7126 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7128 const char *p = (const char*)data;
7130 guint32 i, j, num_named;
7134 mono_class_init (method->klass);
7137 attr = mono_object_new (mono_domain_get (), method->klass);
7138 mono_runtime_invoke (method, attr, NULL, NULL);
7142 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7145 /*g_print ("got attr %s\n", method->klass->name);*/
7147 /* Allocate using alloca so it gets GC tracking */
7148 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7152 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7153 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7157 attr = mono_object_new (mono_domain_get (), method->klass);
7158 mono_runtime_invoke (method, attr, params, NULL);
7159 free_param_data (method->signature, params);
7160 num_named = read16 (named);
7162 for (j = 0; j < num_named; j++) {
7164 char *name, named_type, data_type;
7165 named_type = *named++;
7166 data_type = *named++; /* type of data */
7167 if (data_type == MONO_TYPE_SZARRAY)
7168 data_type = *named++;
7169 if (data_type == MONO_TYPE_ENUM) {
7172 type_len = mono_metadata_decode_blob_size (named, &named);
7173 type_name = g_malloc (type_len + 1);
7174 memcpy (type_name, named, type_len);
7175 type_name [type_len] = 0;
7177 /* FIXME: lookup the type and check type consistency */
7180 name_len = mono_metadata_decode_blob_size (named, &named);
7181 name = g_malloc (name_len + 1);
7182 memcpy (name, named, name_len);
7183 name [name_len] = 0;
7185 if (named_type == 0x53) {
7186 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7187 void *val = load_cattr_value (image, field->type, named, &named);
7188 mono_field_set_value (attr, field, val);
7189 if (!type_is_reference (field->type))
7191 } else if (named_type == 0x54) {
7194 MonoType *prop_type;
7196 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7197 /* can we have more that 1 arg in a custom attr named property? */
7198 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7199 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7200 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7201 mono_property_set_value (prop, attr, pparams, NULL);
7202 if (!type_is_reference (prop_type))
7203 g_free (pparams [0]);
7212 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7214 MonoArray *typedargs, *namedargs;
7215 MonoClass *attrklass;
7216 static MonoMethod *ctor;
7219 const char *p = (const char*)data;
7221 guint32 i, j, num_named;
7224 mono_class_init (method->klass);
7227 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7229 domain = mono_domain_get ();
7231 /* This is for Attributes with no parameters */
7232 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7233 params [0] = mono_method_get_object (domain, method, NULL);
7234 params [1] = params [2] = NULL;
7235 mono_runtime_invoke (method, attr, params, NULL);
7239 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7242 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7246 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7247 MonoObject *obj, *typedarg;
7250 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7251 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7252 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7253 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7254 mono_array_setref (typedargs, i, typedarg);
7256 if (!type_is_reference (mono_method_signature (method)->params [i]))
7261 num_named = read16 (named);
7262 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7264 attrklass = method->klass;
7265 for (j = 0; j < num_named; j++) {
7267 char *name, named_type, data_type;
7268 named_type = *named++;
7269 data_type = *named++; /* type of data */
7270 if (data_type == MONO_TYPE_SZARRAY)
7271 data_type = *named++;
7272 if (data_type == MONO_TYPE_ENUM) {
7275 type_len = mono_metadata_decode_blob_size (named, &named);
7276 type_name = g_malloc (type_len + 1);
7277 memcpy (type_name, named, type_len);
7278 type_name [type_len] = 0;
7280 /* FIXME: lookup the type and check type consistency */
7283 name_len = mono_metadata_decode_blob_size (named, &named);
7284 name = g_malloc (name_len + 1);
7285 memcpy (name, named, name_len);
7286 name [name_len] = 0;
7288 if (named_type == 0x53) {
7289 MonoObject *obj, *typedarg, *namedarg;
7290 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7291 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7293 minfo = mono_field_get_object (domain, NULL, field);
7294 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7295 typedarg = create_cattr_typed_arg (field->type, obj);
7296 namedarg = create_cattr_named_arg (minfo, typedarg);
7297 mono_array_setref (namedargs, j, namedarg);
7298 if (!type_is_reference (field->type))
7300 } else if (named_type == 0x54) {
7301 MonoObject *obj, *typedarg, *namedarg;
7302 MonoType *prop_type;
7304 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7306 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7307 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7308 minfo = mono_property_get_object (domain, NULL, prop);
7309 val = load_cattr_value (image, prop_type, named, &named);
7310 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7311 typedarg = create_cattr_typed_arg (prop_type, obj);
7312 namedarg = create_cattr_named_arg (minfo, typedarg);
7313 mono_array_setref (namedargs, j, namedarg);
7314 if (!type_is_reference (prop_type))
7319 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7320 params [0] = mono_method_get_object (domain, method, NULL);
7321 params [1] = typedargs;
7322 params [2] = namedargs;
7323 mono_runtime_invoke (ctor, attr, params, NULL);
7328 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7334 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7335 for (i = 0; i < cinfo->num_attrs; ++i) {
7336 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7337 mono_array_setref (result, i, attr);
7343 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7350 for (i = 0; i < cinfo->num_attrs; ++i) {
7351 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7355 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7357 for (i = 0; i < cinfo->num_attrs; ++i) {
7358 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7359 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7360 mono_array_setref (result, n, attr);
7368 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7374 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7375 for (i = 0; i < cinfo->num_attrs; ++i) {
7376 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7377 mono_array_setref (result, i, attr);
7383 * mono_custom_attrs_from_index:
7385 * Returns: NULL if no attributes are found or if a loading error occurs.
7388 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7390 guint32 mtoken, i, len;
7391 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7393 MonoCustomAttrInfo *ainfo;
7394 GList *tmp, *list = NULL;
7397 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7399 i = mono_metadata_custom_attrs_from_index (image, idx);
7403 while (i < ca->rows) {
7404 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7406 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7409 len = g_list_length (list);
7412 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7413 ainfo->num_attrs = len;
7414 ainfo->image = image;
7415 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7416 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7417 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7418 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7419 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7420 mtoken |= MONO_TOKEN_METHOD_DEF;
7422 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7423 mtoken |= MONO_TOKEN_MEMBER_REF;
7426 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7429 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7430 if (!ainfo->attrs [i].ctor) {
7431 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7436 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7437 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7438 ainfo->attrs [i].data = (guchar*)data;
7446 mono_custom_attrs_from_method (MonoMethod *method)
7448 MonoCustomAttrInfo *cinfo;
7452 * An instantiated method has the same cattrs as the generic method definition.
7454 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7455 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7457 if (method->is_inflated)
7458 method = ((MonoMethodInflated *) method)->declaring;
7460 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (method)))
7462 idx = mono_method_get_index (method);
7463 idx <<= MONO_CUSTOM_ATTR_BITS;
7464 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7465 return mono_custom_attrs_from_index (method->klass->image, idx);
7469 mono_custom_attrs_from_class (MonoClass *klass)
7471 MonoCustomAttrInfo *cinfo;
7474 if (klass->generic_class)
7475 klass = klass->generic_class->container_class;
7477 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (klass)))
7479 idx = mono_metadata_token_index (klass->type_token);
7480 idx <<= MONO_CUSTOM_ATTR_BITS;
7481 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7482 return mono_custom_attrs_from_index (klass->image, idx);
7486 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7488 MonoCustomAttrInfo *cinfo;
7491 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (assembly)))
7493 idx = 1; /* there is only one assembly */
7494 idx <<= MONO_CUSTOM_ATTR_BITS;
7495 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7496 return mono_custom_attrs_from_index (assembly->image, idx);
7499 static MonoCustomAttrInfo*
7500 mono_custom_attrs_from_module (MonoImage *image)
7502 MonoCustomAttrInfo *cinfo;
7505 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (image)))
7507 idx = 1; /* there is only one module */
7508 idx <<= MONO_CUSTOM_ATTR_BITS;
7509 idx |= MONO_CUSTOM_ATTR_MODULE;
7510 return mono_custom_attrs_from_index (image, idx);
7514 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7516 MonoCustomAttrInfo *cinfo;
7519 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (property)))
7521 idx = find_property_index (klass, property);
7522 idx <<= MONO_CUSTOM_ATTR_BITS;
7523 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7524 return mono_custom_attrs_from_index (klass->image, idx);
7528 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7530 MonoCustomAttrInfo *cinfo;
7533 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (event)))
7535 idx = find_event_index (klass, event);
7536 idx <<= MONO_CUSTOM_ATTR_BITS;
7537 idx |= MONO_CUSTOM_ATTR_EVENT;
7538 return mono_custom_attrs_from_index (klass->image, idx);
7542 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7544 MonoCustomAttrInfo *cinfo;
7547 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (field)))
7549 idx = find_field_index (klass, field);
7550 idx <<= MONO_CUSTOM_ATTR_BITS;
7551 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7552 return mono_custom_attrs_from_index (klass->image, idx);
7556 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7559 guint32 i, idx, method_index;
7560 guint32 param_list, param_last, param_pos, found;
7562 MonoReflectionMethodAux *aux;
7565 * An instantiated method has the same cattrs as the generic method definition.
7567 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7568 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7570 if (method->is_inflated)
7571 method = ((MonoMethodInflated *) method)->declaring;
7573 if (method->klass->image->dynamic) {
7574 MonoCustomAttrInfo *res, *ainfo;
7577 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7578 if (!aux || !aux->param_cattr)
7581 /* Need to copy since it will be freed later */
7582 ainfo = aux->param_cattr [param];
7583 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7584 res = g_malloc0 (size);
7585 memcpy (res, ainfo, size);
7589 image = method->klass->image;
7590 method_index = mono_method_get_index (method);
7591 ca = &image->tables [MONO_TABLE_METHOD];
7593 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7594 if (method_index == ca->rows) {
7595 ca = &image->tables [MONO_TABLE_PARAM];
7596 param_last = ca->rows + 1;
7598 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7599 ca = &image->tables [MONO_TABLE_PARAM];
7602 for (i = param_list; i < param_last; ++i) {
7603 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7604 if (param_pos == param) {
7612 idx <<= MONO_CUSTOM_ATTR_BITS;
7613 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7614 return mono_custom_attrs_from_index (image, idx);
7618 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7622 for (i = 0; i < ainfo->num_attrs; ++i) {
7623 klass = ainfo->attrs [i].ctor->klass;
7624 if (mono_class_has_parent (klass, attr_klass))
7631 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7638 for (i = 0; i < ainfo->num_attrs; ++i) {
7639 klass = ainfo->attrs [i].ctor->klass;
7640 if (mono_class_has_parent (klass, attr_klass)) {
7645 if (attr_index == -1)
7648 attrs = mono_custom_attrs_construct (ainfo);
7650 return mono_array_get (attrs, MonoObject*, attr_index);
7656 * mono_reflection_get_custom_attrs_info:
7657 * @obj: a reflection object handle
7659 * Return the custom attribute info for attributes defined for the
7660 * reflection handle @obj. The objects.
7663 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7666 MonoCustomAttrInfo *cinfo = NULL;
7668 klass = obj->vtable->klass;
7669 if (klass == mono_defaults.monotype_class) {
7670 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7671 klass = mono_class_from_mono_type (rtype->type);
7672 cinfo = mono_custom_attrs_from_class (klass);
7673 } else if (strcmp ("Assembly", klass->name) == 0) {
7674 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7675 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7676 } else if (strcmp ("Module", klass->name) == 0) {
7677 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7678 cinfo = mono_custom_attrs_from_module (module->image);
7679 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7680 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7681 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7682 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7683 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7684 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7685 } else if (strcmp ("MonoField", klass->name) == 0) {
7686 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7687 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7688 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7689 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7690 cinfo = mono_custom_attrs_from_method (rmethod->method);
7691 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7692 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7693 cinfo = mono_custom_attrs_from_method (rmethod->method);
7694 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7695 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7696 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7697 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7698 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7699 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7700 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7701 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7702 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7703 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7704 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7705 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7706 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7707 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7708 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7709 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7710 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7711 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7712 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7713 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7714 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7715 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7716 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
7717 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
7718 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
7719 } else { /* handle other types here... */
7720 g_error ("get custom attrs not yet supported for %s", klass->name);
7727 * mono_reflection_get_custom_attrs_by_type:
7728 * @obj: a reflection object handle
7730 * Return an array with all the custom attributes defined of the
7731 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7732 * of that type are returned. The objects are fully build. Return NULL if a loading error
7736 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7739 MonoCustomAttrInfo *cinfo;
7741 cinfo = mono_reflection_get_custom_attrs_info (obj);
7744 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7746 result = mono_custom_attrs_construct (cinfo);
7748 mono_custom_attrs_free (cinfo);
7750 if (mono_loader_get_last_error ())
7752 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
7759 * mono_reflection_get_custom_attrs:
7760 * @obj: a reflection object handle
7762 * Return an array with all the custom attributes defined of the
7763 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
7767 mono_reflection_get_custom_attrs (MonoObject *obj)
7769 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7773 * mono_reflection_get_custom_attrs_data:
7774 * @obj: a reflection obj handle
7776 * Returns an array of System.Reflection.CustomAttributeData,
7777 * which include information about attributes reflected on
7778 * types loaded using the Reflection Only methods
7781 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7784 MonoCustomAttrInfo *cinfo;
7786 cinfo = mono_reflection_get_custom_attrs_info (obj);
7788 result = mono_custom_attrs_data_construct (cinfo);
7790 mono_custom_attrs_free (cinfo);
7792 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
7797 static MonoReflectionType*
7798 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
7800 MonoMethod *method_get_underlying_system_type;
7802 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
7803 mono_class_get_method_from_name (mono_object_class (t),
7804 "get_UnderlyingSystemType",
7806 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
7810 mono_reflection_type_get_handle (MonoReflectionType* t)
7815 t = mono_reflection_type_get_underlying_system_type (t);
7823 * LOCKING: Assumes the loader lock is held.
7825 static MonoMethodSignature*
7826 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7827 MonoMethodSignature *sig;
7830 count = parameters? mono_array_length (parameters): 0;
7832 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7833 sig->param_count = count;
7834 sig->sentinelpos = -1; /* FIXME */
7835 for (i = 0; i < count; ++i) {
7836 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7837 sig->params [i] = mono_reflection_type_get_handle (pt);
7843 * LOCKING: Assumes the loader lock is held.
7845 static MonoMethodSignature*
7846 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7847 MonoMethodSignature *sig;
7849 sig = parameters_to_signature (mp, ctor->parameters);
7850 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7851 sig->ret = &mono_defaults.void_class->byval_arg;
7856 * LOCKING: Assumes the loader lock is held.
7858 static MonoMethodSignature*
7859 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7860 MonoMethodSignature *sig;
7862 sig = parameters_to_signature (mp, method->parameters);
7863 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7864 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7865 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7869 static MonoMethodSignature*
7870 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7871 MonoMethodSignature *sig;
7873 sig = parameters_to_signature (NULL, method->parameters);
7874 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7875 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7876 sig->generic_param_count = 0;
7881 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7883 MonoClass *klass = mono_object_class (prop);
7884 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7885 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7886 *name = mono_string_to_utf8 (pb->name);
7887 *type = pb->type->type;
7889 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7890 *name = g_strdup (p->property->name);
7891 if (p->property->get)
7892 *type = mono_method_signature (p->property->get)->ret;
7894 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7899 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7901 MonoClass *klass = mono_object_class (field);
7902 if (strcmp (klass->name, "FieldBuilder") == 0) {
7903 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7904 *name = mono_string_to_utf8 (fb->name);
7905 *type = fb->type->type;
7907 MonoReflectionField *f = (MonoReflectionField *)field;
7908 *name = g_strdup (f->field->name);
7909 *type = f->field->type;
7914 * Encode a value in a custom attribute stream of bytes.
7915 * The value to encode is either supplied as an object in argument val
7916 * (valuetypes are boxed), or as a pointer to the data in the
7918 * @type represents the type of the value
7919 * @buffer is the start of the buffer
7920 * @p the current position in the buffer
7921 * @buflen contains the size of the buffer and is used to return the new buffer size
7922 * if this needs to be realloced.
7923 * @retbuffer and @retp return the start and the position of the buffer
7926 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7928 MonoTypeEnum simple_type;
7930 if ((p-buffer) + 10 >= *buflen) {
7933 newbuf = g_realloc (buffer, *buflen);
7934 p = newbuf + (p-buffer);
7938 argval = ((char*)arg + sizeof (MonoObject));
7939 simple_type = type->type;
7941 switch (simple_type) {
7942 case MONO_TYPE_BOOLEAN:
7947 case MONO_TYPE_CHAR:
7950 swap_with_size (p, argval, 2, 1);
7956 swap_with_size (p, argval, 4, 1);
7960 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
7970 swap_with_size (p, argval, 8, 1);
7976 swap_with_size (p, argval, 8, 1);
7979 case MONO_TYPE_VALUETYPE:
7980 if (type->data.klass->enumtype) {
7981 simple_type = type->data.klass->enum_basetype->type;
7984 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7987 case MONO_TYPE_STRING: {
7994 str = mono_string_to_utf8 ((MonoString*)arg);
7995 slen = strlen (str);
7996 if ((p-buffer) + 10 + slen >= *buflen) {
8000 newbuf = g_realloc (buffer, *buflen);
8001 p = newbuf + (p-buffer);
8004 mono_metadata_encode_value (slen, p, &p);
8005 memcpy (p, str, slen);
8010 case MONO_TYPE_CLASS: {
8018 k = mono_object_class (arg);
8019 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8020 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8021 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8024 if (rt && (rtc = mono_object_class (rt)) &&
8025 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8026 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8027 arg = (MonoObject *) rt;
8030 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8033 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8034 slen = strlen (str);
8035 if ((p-buffer) + 10 + slen >= *buflen) {
8039 newbuf = g_realloc (buffer, *buflen);
8040 p = newbuf + (p-buffer);
8043 mono_metadata_encode_value (slen, p, &p);
8044 memcpy (p, str, slen);
8049 case MONO_TYPE_SZARRAY: {
8051 MonoClass *eclass, *arg_eclass;
8054 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8057 len = mono_array_length ((MonoArray*)arg);
8059 *p++ = (len >> 8) & 0xff;
8060 *p++ = (len >> 16) & 0xff;
8061 *p++ = (len >> 24) & 0xff;
8063 *retbuffer = buffer;
8064 eclass = type->data.klass;
8065 arg_eclass = mono_object_class (arg)->element_class;
8068 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8069 eclass = mono_defaults.object_class;
8071 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8072 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8073 int elsize = mono_class_array_element_size (arg_eclass);
8074 for (i = 0; i < len; ++i) {
8075 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8078 } else if (eclass->valuetype && arg_eclass->valuetype) {
8079 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8080 int elsize = mono_class_array_element_size (eclass);
8081 for (i = 0; i < len; ++i) {
8082 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8086 for (i = 0; i < len; ++i) {
8087 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8092 case MONO_TYPE_OBJECT: {
8098 * The parameter type is 'object' but the type of the actual
8099 * argument is not. So we have to add type information to the blob
8100 * too. This is completely undocumented in the spec.
8104 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8109 klass = mono_object_class (arg);
8111 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8114 } else if (klass->enumtype) {
8116 } else if (klass == mono_defaults.string_class) {
8117 simple_type = MONO_TYPE_STRING;
8120 } else if (klass->rank == 1) {
8122 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8123 /* See Partition II, Appendix B3 */
8126 *p++ = klass->element_class->byval_arg.type;
8127 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8129 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8130 *p++ = simple_type = klass->byval_arg.type;
8133 g_error ("unhandled type in custom attr");
8135 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8136 slen = strlen (str);
8137 if ((p-buffer) + 10 + slen >= *buflen) {
8141 newbuf = g_realloc (buffer, *buflen);
8142 p = newbuf + (p-buffer);
8145 mono_metadata_encode_value (slen, p, &p);
8146 memcpy (p, str, slen);
8149 simple_type = klass->enum_basetype->type;
8153 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8156 *retbuffer = buffer;
8160 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8162 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8163 char *str = type_get_qualified_name (type, NULL);
8164 int slen = strlen (str);
8168 * This seems to be optional...
8171 mono_metadata_encode_value (slen, p, &p);
8172 memcpy (p, str, slen);
8175 } else if (type->type == MONO_TYPE_OBJECT) {
8177 } else if (type->type == MONO_TYPE_CLASS) {
8178 /* it should be a type: encode_cattr_value () has the check */
8181 mono_metadata_encode_value (type->type, p, &p);
8182 if (type->type == MONO_TYPE_SZARRAY)
8183 /* See the examples in Partition VI, Annex B */
8184 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8191 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8194 /* Preallocate a large enough buffer */
8195 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8196 char *str = type_get_qualified_name (type, NULL);
8199 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8200 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8206 len += strlen (name);
8208 if ((p-buffer) + 20 + len >= *buflen) {
8212 newbuf = g_realloc (buffer, *buflen);
8213 p = newbuf + (p-buffer);
8217 encode_field_or_prop_type (type, p, &p);
8219 len = strlen (name);
8220 mono_metadata_encode_value (len, p, &p);
8221 memcpy (p, name, len);
8223 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8225 *retbuffer = buffer;
8229 * mono_reflection_get_custom_attrs_blob:
8230 * @ctor: custom attribute constructor
8231 * @ctorArgs: arguments o the constructor
8237 * Creates the blob of data that needs to be saved in the metadata and that represents
8238 * the custom attributed described by @ctor, @ctorArgs etc.
8239 * Returns: a Byte array representing the blob of data.
8242 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8245 MonoMethodSignature *sig;
8250 MONO_ARCH_SAVE_REGS;
8252 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8253 /* sig is freed later so allocate it in the heap */
8254 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8256 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8259 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8261 p = buffer = g_malloc (buflen);
8262 /* write the prolog */
8265 for (i = 0; i < sig->param_count; ++i) {
8266 arg = mono_array_get (ctorArgs, MonoObject*, i);
8267 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8271 i += mono_array_length (properties);
8273 i += mono_array_length (fields);
8275 *p++ = (i >> 8) & 0xff;
8278 for (i = 0; i < mono_array_length (properties); ++i) {
8282 prop = mono_array_get (properties, gpointer, i);
8283 get_prop_name_and_type (prop, &pname, &ptype);
8284 *p++ = 0x54; /* PROPERTY signature */
8285 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8292 for (i = 0; i < mono_array_length (fields); ++i) {
8296 field = mono_array_get (fields, gpointer, i);
8297 get_field_name_and_type (field, &fname, &ftype);
8298 *p++ = 0x53; /* FIELD signature */
8299 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8304 g_assert (p - buffer <= buflen);
8305 buflen = p - buffer;
8306 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8307 p = mono_array_addr (result, char, 0);
8308 memcpy (p, buffer, buflen);
8310 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8316 static void* reflection_info_desc = NULL;
8317 #define MOVING_GC_REGISTER(addr) do { \
8318 if (!reflection_info_desc) { \
8320 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8322 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8325 #define MOVING_GC_REGISTER(addr)
8329 * mono_reflection_setup_internal_class:
8330 * @tb: a TypeBuilder object
8332 * Creates a MonoClass that represents the TypeBuilder.
8333 * This is a trick that lets us simplify a lot of reflection code
8334 * (and will allow us to support Build and Run assemblies easier).
8337 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8339 MonoClass *klass, *parent;
8341 MONO_ARCH_SAVE_REGS;
8343 mono_loader_lock ();
8346 /* check so we can compile corlib correctly */
8347 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8348 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8349 parent = tb->parent->type->data.klass;
8351 parent = my_mono_class_from_mono_type (tb->parent->type);
8357 /* the type has already being created: it means we just have to change the parent */
8358 if (tb->type.type) {
8359 klass = mono_class_from_mono_type (tb->type.type);
8360 klass->parent = NULL;
8361 /* fool mono_class_setup_parent */
8362 klass->supertypes = NULL;
8363 mono_class_setup_parent (klass, parent);
8364 mono_class_setup_mono_type (klass);
8365 mono_loader_unlock ();
8369 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8371 klass->image = &tb->module->dynamic_image->image;
8373 klass->inited = 1; /* we lie to the runtime */
8374 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8375 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8376 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8377 klass->flags = tb->attrs;
8379 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8381 klass->element_class = klass;
8383 MOVING_GC_REGISTER (&klass->reflection_info);
8384 klass->reflection_info = tb;
8386 /* Put into cache so mono_class_get () will find it */
8387 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8389 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8390 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8392 if (parent != NULL) {
8393 mono_class_setup_parent (klass, parent);
8394 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8395 const char *old_n = klass->name;
8396 /* trick to get relative numbering right when compiling corlib */
8397 klass->name = "BuildingObject";
8398 mono_class_setup_parent (klass, mono_defaults.object_class);
8399 klass->name = old_n;
8402 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8403 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8404 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8405 klass->instance_size = sizeof (MonoObject);
8406 klass->size_inited = 1;
8407 mono_class_setup_vtable_general (klass, NULL, 0);
8410 mono_class_setup_mono_type (klass);
8412 mono_class_setup_supertypes (klass);
8415 * FIXME: handle interfaces.
8418 tb->type.type = &klass->byval_arg;
8420 if (tb->nesting_type) {
8421 g_assert (tb->nesting_type->type);
8422 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8425 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8427 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8429 mono_loader_unlock ();
8433 * mono_reflection_setup_generic_class:
8434 * @tb: a TypeBuilder object
8436 * Setup the generic class before adding the first generic parameter.
8439 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8443 MONO_ARCH_SAVE_REGS;
8445 klass = my_mono_class_from_mono_type (tb->type.type);
8446 if (tb->generic_container)
8449 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8450 tb->generic_container->owner.klass = klass;
8454 * mono_reflection_create_generic_class:
8455 * @tb: a TypeBuilder object
8457 * Creates the generic class after all generic parameters have been added.
8460 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8465 MONO_ARCH_SAVE_REGS;
8467 klass = my_mono_class_from_mono_type (tb->type.type);
8469 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8471 if (klass->generic_container || (count == 0))
8474 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8476 klass->generic_container = tb->generic_container;
8478 klass->generic_container->type_argc = count;
8479 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8481 for (i = 0; i < count; i++) {
8482 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8483 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8484 g_assert (klass->generic_container->type_params [i].owner);
8487 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8491 * mono_reflection_create_internal_class:
8492 * @tb: a TypeBuilder object
8494 * Actually create the MonoClass that is associated with the TypeBuilder.
8497 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8501 MONO_ARCH_SAVE_REGS;
8503 klass = my_mono_class_from_mono_type (tb->type.type);
8505 mono_loader_lock ();
8506 if (klass->enumtype && klass->enum_basetype == NULL) {
8507 MonoReflectionFieldBuilder *fb;
8510 g_assert (tb->fields != NULL);
8511 g_assert (mono_array_length (tb->fields) >= 1);
8513 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8515 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8516 mono_loader_unlock ();
8520 klass->enum_basetype = fb->type->type;
8521 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8522 if (!klass->element_class)
8523 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8526 * get the element_class from the current corlib.
8528 ec = default_class_from_mono_type (klass->enum_basetype);
8529 klass->instance_size = ec->instance_size;
8530 klass->size_inited = 1;
8532 * this is almost safe to do with enums and it's needed to be able
8533 * to create objects of the enum type (for use in SetConstant).
8535 /* FIXME: Does this mean enums can't have method overrides ? */
8536 mono_class_setup_vtable_general (klass, NULL, 0);
8538 mono_loader_unlock ();
8541 static MonoMarshalSpec*
8542 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8543 MonoReflectionMarshal *minfo)
8545 MonoMarshalSpec *res;
8547 res = g_new0 (MonoMarshalSpec, 1);
8548 res->native = minfo->type;
8550 switch (minfo->type) {
8551 case MONO_NATIVE_LPARRAY:
8552 res->data.array_data.elem_type = minfo->eltype;
8553 if (minfo->has_size) {
8554 res->data.array_data.param_num = minfo->param_num;
8555 res->data.array_data.num_elem = minfo->count;
8556 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8559 res->data.array_data.param_num = -1;
8560 res->data.array_data.num_elem = -1;
8561 res->data.array_data.elem_mult = -1;
8565 case MONO_NATIVE_BYVALTSTR:
8566 case MONO_NATIVE_BYVALARRAY:
8567 res->data.array_data.num_elem = minfo->count;
8570 case MONO_NATIVE_CUSTOM:
8571 if (minfo->marshaltyperef)
8572 res->data.custom_data.custom_name =
8573 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8575 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8585 MonoReflectionMarshal*
8586 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8587 MonoMarshalSpec *spec)
8589 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8590 MonoReflectionMarshal *minfo;
8593 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8594 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8595 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8596 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8599 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8600 minfo->type = spec->native;
8602 switch (minfo->type) {
8603 case MONO_NATIVE_LPARRAY:
8604 minfo->eltype = spec->data.array_data.elem_type;
8605 minfo->count = spec->data.array_data.num_elem;
8606 minfo->param_num = spec->data.array_data.param_num;
8609 case MONO_NATIVE_BYVALTSTR:
8610 case MONO_NATIVE_BYVALARRAY:
8611 minfo->count = spec->data.array_data.num_elem;
8614 case MONO_NATIVE_CUSTOM:
8615 if (spec->data.custom_data.custom_name) {
8616 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8618 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8620 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8622 if (spec->data.custom_data.cookie)
8623 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8634 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8635 ReflectionMethodBuilder *rmb,
8636 MonoMethodSignature *sig)
8639 MonoMethodNormal *pm;
8640 MonoMarshalSpec **specs;
8641 MonoReflectionMethodAux *method_aux;
8647 * Methods created using a MethodBuilder should have their memory allocated
8648 * inside the image mempool, while dynamic methods should have their memory
8651 dynamic = rmb->refs != NULL;
8652 mp = dynamic ? NULL : klass->image->mempool;
8655 g_assert (!klass->generic_class);
8657 mono_loader_lock ();
8659 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8660 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8661 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8663 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8665 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8667 pm = (MonoMethodNormal*)m;
8669 m->dynamic = dynamic;
8671 m->flags = rmb->attrs;
8672 m->iflags = rmb->iattrs;
8673 m->name = mp_string_to_utf8 (mp, rmb->name);
8676 m->skip_visibility = rmb->skip_visibility;
8678 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8680 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8681 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8684 m->signature->pinvoke = 1;
8685 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8686 m->signature->pinvoke = 1;
8688 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8690 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8691 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8693 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8695 if (klass->image->dynamic)
8696 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8698 mono_loader_unlock ();
8701 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8702 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8703 MonoMethodHeader *header;
8705 gint32 max_stack, i;
8706 gint32 num_locals = 0;
8707 gint32 num_clauses = 0;
8711 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8712 code_size = rmb->ilgen->code_len;
8713 max_stack = rmb->ilgen->max_stack;
8714 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8715 if (rmb->ilgen->ex_handlers)
8716 num_clauses = method_count_clauses (rmb->ilgen);
8719 code = mono_array_addr (rmb->code, guint8, 0);
8720 code_size = mono_array_length (rmb->code);
8721 /* we probably need to run a verifier on the code... */
8731 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8732 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8733 header->code_size = code_size;
8734 header->code = mp_g_malloc (mp, code_size);
8735 memcpy ((char*)header->code, code, code_size);
8736 header->max_stack = max_stack;
8737 header->init_locals = rmb->init_locals;
8738 header->num_locals = num_locals;
8740 for (i = 0; i < num_locals; ++i) {
8741 MonoReflectionLocalBuilder *lb =
8742 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8744 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8745 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8748 header->num_clauses = num_clauses;
8750 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8751 rmb->ilgen, num_clauses);
8754 pm->header = header;
8757 if (rmb->generic_params) {
8758 int count = mono_array_length (rmb->generic_params);
8759 MonoGenericContainer *container;
8761 m->generic_container = container = rmb->generic_container;
8762 container->type_argc = count;
8763 container->type_params = g_new0 (MonoGenericParam, count);
8764 container->owner.method = m;
8766 for (i = 0; i < count; i++) {
8767 MonoReflectionGenericParam *gp =
8768 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8770 container->type_params [i] = *gp->type.type->data.generic_param;
8773 if (klass->generic_container) {
8774 container->parent = klass->generic_container;
8775 container->context.class_inst = klass->generic_container->context.class_inst;
8777 container->context.method_inst = mono_get_shared_generic_inst (container);
8781 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8785 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8787 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8788 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8789 for (i = 0; i < rmb->nrefs; ++i)
8790 data [i + 1] = rmb->refs [i];
8795 /* Parameter info */
8798 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8799 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8800 for (i = 0; i <= m->signature->param_count; ++i) {
8801 MonoReflectionParamBuilder *pb;
8802 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8803 if ((i > 0) && (pb->attrs)) {
8804 /* Make a copy since it might point to a shared type structure */
8805 /* FIXME: Alloc this from a mempool */
8806 m->signature->params [i - 1] = mono_metadata_type_dup (NULL, m->signature->params [i - 1]);
8807 m->signature->params [i - 1]->attrs = pb->attrs;
8810 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8811 MonoDynamicImage *assembly;
8812 guint32 idx, def_type, len;
8816 if (!method_aux->param_defaults) {
8817 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8818 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8820 assembly = (MonoDynamicImage*)klass->image;
8821 idx = encode_constant (assembly, pb->def_value, &def_type);
8822 /* Copy the data from the blob since it might get realloc-ed */
8823 p = assembly->blob.data + idx;
8824 len = mono_metadata_decode_blob_size (p, &p2);
8826 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8827 method_aux->param_default_types [i] = def_type;
8828 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8832 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
8834 if (!method_aux->param_cattr)
8835 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8836 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8842 /* Parameter marshalling */
8845 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8846 MonoReflectionParamBuilder *pb;
8847 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8848 if (pb->marshal_info) {
8850 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8851 specs [pb->position] =
8852 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8856 if (specs != NULL) {
8858 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8859 method_aux->param_marshall = specs;
8862 if (klass->image->dynamic && method_aux)
8863 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8865 mono_loader_unlock ();
8871 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8873 ReflectionMethodBuilder rmb;
8874 MonoMethodSignature *sig;
8876 mono_loader_lock ();
8877 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8878 mono_loader_unlock ();
8880 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8882 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8883 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8885 /* If we are in a generic class, we might be called multiple times from inflate_method */
8886 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
8887 /* ilgen is no longer needed */
8895 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8897 ReflectionMethodBuilder rmb;
8898 MonoMethodSignature *sig;
8900 mono_loader_lock ();
8901 sig = method_builder_to_signature (klass->image->mempool, mb);
8902 mono_loader_unlock ();
8904 reflection_methodbuilder_from_method_builder (&rmb, mb);
8906 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8907 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8909 /* If we are in a generic class, we might be called multiple times from inflate_method */
8910 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
8911 /* ilgen is no longer needed */
8917 static MonoClassField*
8918 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8920 MonoClassField *field;
8924 field = g_new0 (MonoClassField, 1);
8926 field->name = mono_string_to_utf8 (fb->name);
8928 /* FIXME: handle type modifiers */
8929 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8930 field->type->attrs = fb->attrs;
8932 field->type = fb->type->type;
8934 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8935 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8936 if (fb->offset != -1)
8937 field->offset = fb->offset;
8938 field->parent = klass;
8939 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8941 if (fb->def_value) {
8942 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8943 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8944 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8945 /* Copy the data from the blob since it might get realloc-ed */
8946 p = assembly->blob.data + idx;
8947 len = mono_metadata_decode_blob_size (p, &p2);
8949 field->data = g_malloc (len);
8950 memcpy ((gpointer)field->data, p, len);
8957 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8960 MonoReflectionTypeBuilder *tb = NULL;
8961 gboolean is_dynamic = FALSE;
8965 mono_loader_lock ();
8967 domain = mono_object_domain (type);
8969 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8970 tb = (MonoReflectionTypeBuilder *) type;
8973 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8974 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8976 tb = rgi->generic_type;
8980 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
8981 if (tb && tb->generic_container)
8982 mono_reflection_create_generic_class (tb);
8984 klass = mono_class_from_mono_type (type->type);
8985 if (!klass->generic_container) {
8986 mono_loader_unlock ();
8990 if (klass->wastypebuilder) {
8991 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8996 mono_loader_unlock ();
8998 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9000 return &geninst->byval_arg;
9004 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9006 MonoGenericClass *gclass;
9007 MonoGenericInst *inst;
9009 g_assert (klass->generic_container);
9011 inst = mono_metadata_get_generic_inst (type_argc, types);
9012 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9014 return mono_generic_class_get_class (gclass);
9017 MonoReflectionMethod*
9018 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9021 MonoMethod *method, *inflated;
9022 MonoMethodInflated *imethod;
9023 MonoReflectionMethodBuilder *mb = NULL;
9024 MonoGenericContext tmp_context;
9025 MonoGenericInst *ginst;
9026 MonoType **type_argv;
9029 MONO_ARCH_SAVE_REGS;
9030 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9031 MonoReflectionTypeBuilder *tb;
9034 mb = (MonoReflectionMethodBuilder *) rmethod;
9035 tb = (MonoReflectionTypeBuilder *) mb->type;
9036 klass = mono_class_from_mono_type (tb->type.type);
9038 method = methodbuilder_to_mono_method (klass, mb);
9040 method = rmethod->method;
9043 klass = method->klass;
9045 if (method->is_inflated)
9046 method = ((MonoMethodInflated *) method)->declaring;
9048 count = mono_method_signature (method)->generic_param_count;
9049 if (count != mono_array_length (types))
9052 type_argv = g_new0 (MonoType *, count);
9053 for (i = 0; i < count; i++) {
9054 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9055 type_argv [i] = garg->type;
9057 ginst = mono_metadata_get_generic_inst (count, type_argv);
9060 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9061 tmp_context.method_inst = ginst;
9063 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9064 imethod = (MonoMethodInflated *) inflated;
9066 MOVING_GC_REGISTER (&imethod->reflection_info);
9067 imethod->reflection_info = rmethod;
9069 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9073 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
9075 MonoMethodInflated *imethod;
9076 MonoGenericContext *context;
9079 klass = mono_class_from_mono_type (type->type.type);
9080 g_assert (klass->generic_class);
9081 context = mono_class_get_context (klass);
9083 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9084 if (method->generic_container) {
9085 MOVING_GC_REGISTER (&imethod->reflection_info);
9086 imethod->reflection_info = obj;
9088 return (MonoMethod *) imethod;
9092 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9097 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9099 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9100 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9101 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9102 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9103 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9104 method = ((MonoReflectionMethod *) obj)->method;
9106 method = NULL; /* prevent compiler warning */
9107 g_assert_not_reached ();
9110 return inflate_mono_method (type, method, obj);
9114 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9115 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9118 MonoGenericClass *gclass;
9119 MonoDynamicGenericClass *dgclass;
9120 MonoClass *klass, *gklass;
9123 MONO_ARCH_SAVE_REGS;
9125 klass = mono_class_from_mono_type (type->type.type);
9126 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9127 gclass = type->type.type->data.generic_class;
9129 g_assert (gclass->is_dynamic);
9130 dgclass = (MonoDynamicGenericClass *) gclass;
9132 if (dgclass->initialized)
9135 gklass = gclass->container_class;
9136 mono_class_init (gklass);
9138 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9139 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9140 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9141 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9142 dgclass->count_events = events ? mono_array_length (events) : 0;
9144 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9145 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9146 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9147 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9148 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9150 for (i = 0; i < dgclass->count_methods; i++) {
9151 MonoObject *obj = mono_array_get (methods, gpointer, i);
9153 dgclass->methods [i] = inflate_method (type, obj);
9156 for (i = 0; i < dgclass->count_ctors; i++) {
9157 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9159 dgclass->ctors [i] = inflate_method (type, obj);
9162 for (i = 0; i < dgclass->count_fields; i++) {
9163 MonoObject *obj = mono_array_get (fields, gpointer, i);
9164 MonoClassField *field;
9165 MonoInflatedField *ifield;
9167 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9168 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9169 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9170 field = ((MonoReflectionField *) obj)->field;
9172 field = NULL; /* prevent compiler warning */
9173 g_assert_not_reached ();
9176 ifield = g_new0 (MonoInflatedField, 1);
9177 ifield->generic_type = field->type;
9178 MOVING_GC_REGISTER (&ifield->reflection_info);
9179 ifield->reflection_info = obj;
9181 dgclass->fields [i] = *field;
9182 dgclass->fields [i].parent = klass;
9183 dgclass->fields [i].generic_info = ifield;
9184 dgclass->fields [i].type = mono_class_inflate_generic_type (
9185 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9188 for (i = 0; i < dgclass->count_properties; i++) {
9189 MonoObject *obj = mono_array_get (properties, gpointer, i);
9190 MonoProperty *property = &dgclass->properties [i];
9192 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9193 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9195 property->parent = klass;
9196 property->attrs = pb->attrs;
9197 property->name = mono_string_to_utf8 (pb->name);
9199 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9201 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9202 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9203 *property = *((MonoReflectionProperty *) obj)->property;
9206 property->get = inflate_mono_method (type, property->get, NULL);
9208 property->set = inflate_mono_method (type, property->set, NULL);
9210 g_assert_not_reached ();
9213 for (i = 0; i < dgclass->count_events; i++) {
9214 MonoObject *obj = mono_array_get (events, gpointer, i);
9215 MonoEvent *event = &dgclass->events [i];
9217 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9218 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9220 event->parent = klass;
9221 event->attrs = eb->attrs;
9222 event->name = mono_string_to_utf8 (eb->name);
9224 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9225 if (eb->remove_method)
9226 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9227 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9228 *event = *((MonoReflectionEvent *) obj)->event;
9231 event->add = inflate_mono_method (type, event->add, NULL);
9233 event->remove = inflate_mono_method (type, event->remove, NULL);
9235 g_assert_not_reached ();
9238 dgclass->initialized = TRUE;
9242 ensure_runtime_vtable (MonoClass *klass)
9244 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9247 if (!tb || klass->wastypebuilder)
9250 ensure_runtime_vtable (klass->parent);
9252 num = tb->ctors? mono_array_length (tb->ctors): 0;
9253 num += tb->num_methods;
9254 klass->method.count = num;
9255 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9256 num = tb->ctors? mono_array_length (tb->ctors): 0;
9257 for (i = 0; i < num; ++i)
9258 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9259 num = tb->num_methods;
9261 for (i = 0; i < num; ++i)
9262 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9264 if (tb->interfaces) {
9265 klass->interface_count = mono_array_length (tb->interfaces);
9266 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9267 for (i = 0; i < klass->interface_count; ++i) {
9268 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9269 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9273 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9274 for (i = 0; i < klass->method.count; ++i)
9275 klass->methods [i]->slot = i;
9277 mono_class_setup_interface_offsets (klass);
9281 * The generic vtable is needed even if image->run is not set since some
9282 * runtime code like ves_icall_Type_GetMethodsByName depends on
9283 * method->slot being defined.
9287 * tb->methods could not be freed since it is used for determining
9288 * overrides during dynamic vtable construction.
9293 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9295 MonoReflectionTypeBuilder *tb;
9301 g_assert (klass->image->dynamic);
9303 if (!klass->reflection_info)
9306 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9308 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9312 for (i = 0; i < tb->num_methods; ++i) {
9313 MonoReflectionMethodBuilder *mb =
9314 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9315 if (mb->override_method)
9321 *overrides = g_new0 (MonoMethod*, onum * 2);
9324 for (i = 0; i < tb->num_methods; ++i) {
9325 MonoReflectionMethodBuilder *mb =
9326 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9327 if (mb->override_method) {
9328 (*overrides) [onum * 2] =
9329 mb->override_method->method;
9330 (*overrides) [onum * 2 + 1] =
9333 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9334 g_assert (mb->override_method->method);
9335 g_assert (mb->mhandle);
9342 *num_overrides = onum;
9346 typebuilder_setup_fields (MonoClass *klass)
9348 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9349 MonoReflectionFieldBuilder *fb;
9350 MonoClassField *field;
9355 klass->field.count = tb->num_fields;
9356 klass->field.first = 0;
9358 if (!klass->field.count)
9361 klass->fields = g_new0 (MonoClassField, klass->field.count);
9363 for (i = 0; i < klass->field.count; ++i) {
9364 fb = mono_array_get (tb->fields, gpointer, i);
9365 field = &klass->fields [i];
9366 field->name = mono_string_to_utf8 (fb->name);
9368 /* FIXME: handle type modifiers */
9369 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9370 field->type->attrs = fb->attrs;
9372 field->type = fb->type->type;
9374 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9375 field->data = mono_array_addr (fb->rva_data, char, 0);
9376 if (fb->offset != -1)
9377 field->offset = fb->offset;
9378 field->parent = klass;
9380 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9382 if (fb->def_value) {
9383 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9384 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9385 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9386 /* Copy the data from the blob since it might get realloc-ed */
9387 p = assembly->blob.data + idx;
9388 len = mono_metadata_decode_blob_size (p, &p2);
9390 field->data = g_malloc (len);
9391 memcpy ((gpointer)field->data, p, len);
9394 mono_class_layout_fields (klass);
9398 typebuilder_setup_properties (MonoClass *klass)
9400 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9401 MonoReflectionPropertyBuilder *pb;
9404 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9405 klass->property.first = 0;
9407 klass->properties = g_new0 (MonoProperty, klass->property.count);
9408 for (i = 0; i < klass->property.count; ++i) {
9409 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9410 klass->properties [i].parent = klass;
9411 klass->properties [i].attrs = pb->attrs;
9412 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9414 klass->properties [i].get = pb->get_method->mhandle;
9416 klass->properties [i].set = pb->set_method->mhandle;
9418 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9422 MonoReflectionEvent *
9423 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9425 MonoEvent *event = g_new0 (MonoEvent, 1);
9429 klass = my_mono_class_from_mono_type (tb->type.type);
9431 event->parent = klass;
9432 event->attrs = eb->attrs;
9433 event->name = mono_string_to_utf8 (eb->name);
9435 event->add = eb->add_method->mhandle;
9436 if (eb->remove_method)
9437 event->remove = eb->remove_method->mhandle;
9438 if (eb->raise_method)
9439 event->raise = eb->raise_method->mhandle;
9441 if (eb->other_methods) {
9442 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9443 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9444 MonoReflectionMethodBuilder *mb =
9445 mono_array_get (eb->other_methods,
9446 MonoReflectionMethodBuilder*, j);
9447 event->other [j] = mb->mhandle;
9451 return mono_event_get_object (mono_object_domain (tb), klass, event);
9455 typebuilder_setup_events (MonoClass *klass)
9457 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9458 MonoReflectionEventBuilder *eb;
9461 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9462 klass->event.first = 0;
9464 klass->events = g_new0 (MonoEvent, klass->event.count);
9465 for (i = 0; i < klass->event.count; ++i) {
9466 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9467 klass->events [i].parent = klass;
9468 klass->events [i].attrs = eb->attrs;
9469 klass->events [i].name = mono_string_to_utf8 (eb->name);
9471 klass->events [i].add = eb->add_method->mhandle;
9472 if (eb->remove_method)
9473 klass->events [i].remove = eb->remove_method->mhandle;
9474 if (eb->raise_method)
9475 klass->events [i].raise = eb->raise_method->mhandle;
9477 if (eb->other_methods) {
9478 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9479 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9480 MonoReflectionMethodBuilder *mb =
9481 mono_array_get (eb->other_methods,
9482 MonoReflectionMethodBuilder*, j);
9483 klass->events [i].other [j] = mb->mhandle;
9490 remove_instantiations_of (gpointer key,
9494 MonoType *type = (MonoType*)key;
9495 MonoClass *klass = (MonoClass*)user_data;
9497 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
9504 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9508 MonoReflectionType* res;
9511 MONO_ARCH_SAVE_REGS;
9513 domain = mono_object_domain (tb);
9514 klass = my_mono_class_from_mono_type (tb->type.type);
9516 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9519 * we need to lock the domain because the lock will be taken inside
9520 * So, we need to keep the locking order correct.
9522 mono_domain_lock (domain);
9523 mono_loader_lock ();
9524 if (klass->wastypebuilder) {
9525 mono_loader_unlock ();
9526 mono_domain_unlock (domain);
9527 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9530 * Fields to set in klass:
9531 * the various flags: delegate/unicode/contextbound etc.
9533 klass->flags = tb->attrs;
9534 klass->has_cctor = 1;
9535 klass->has_finalize = 1;
9538 if (!((MonoDynamicImage*)klass->image)->run) {
9539 if (klass->generic_container) {
9540 /* FIXME: The code below can't handle generic classes */
9541 klass->wastypebuilder = TRUE;
9542 mono_loader_unlock ();
9543 mono_domain_unlock (domain);
9544 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9549 /* enums are done right away */
9550 if (!klass->enumtype)
9551 ensure_runtime_vtable (klass);
9554 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9555 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9556 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9560 /* fields and object layout */
9561 if (klass->parent) {
9562 if (!klass->parent->size_inited)
9563 mono_class_init (klass->parent);
9564 klass->instance_size = klass->parent->instance_size;
9565 klass->sizes.class_size = 0;
9566 klass->min_align = klass->parent->min_align;
9567 /* if the type has no fields we won't call the field_setup
9568 * routine which sets up klass->has_references.
9570 klass->has_references |= klass->parent->has_references;
9572 klass->instance_size = sizeof (MonoObject);
9573 klass->min_align = 1;
9576 /* FIXME: handle packing_size and instance_size */
9577 typebuilder_setup_fields (klass);
9579 typebuilder_setup_properties (klass);
9581 typebuilder_setup_events (klass);
9583 klass->wastypebuilder = TRUE;
9586 * If we are a generic TypeBuilder, there might be instantiations in the type cache
9587 * which have type System.Reflection.MonoGenericClass, but after the type is created,
9588 * we want to return normal System.MonoType objects, so clear these out from the cache.
9590 if (domain->type_hash && klass->generic_container)
9591 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
9593 mono_loader_unlock ();
9594 mono_domain_unlock (domain);
9596 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
9597 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
9598 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
9601 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9602 g_assert (res != (MonoReflectionType*)tb);
9608 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9610 MonoGenericParam *param;
9613 MONO_ARCH_SAVE_REGS;
9615 param = g_new0 (MonoGenericParam, 1);
9617 if (gparam->mbuilder) {
9618 if (!gparam->mbuilder->generic_container) {
9619 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9620 gparam->mbuilder->generic_container->is_method = TRUE;
9622 param->owner = gparam->mbuilder->generic_container;
9623 } else if (gparam->tbuilder) {
9624 g_assert (gparam->tbuilder->generic_container);
9625 param->owner = gparam->tbuilder->generic_container;
9628 param->name = mono_string_to_utf8 (gparam->name);
9629 param->num = gparam->index;
9631 image = &gparam->tbuilder->module->dynamic_image->image;
9632 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9634 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
9635 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9637 gparam->type.type = g_new0 (MonoType, 1);
9638 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9639 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9640 gparam->type.type->data.generic_param = param;
9644 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9646 MonoDynamicImage *assembly = sig->module->dynamic_image;
9647 guint32 na = mono_array_length (sig->arguments);
9652 sigbuffer_init (&buf, 32);
9654 sigbuffer_add_value (&buf, 0x07);
9655 sigbuffer_add_value (&buf, na);
9656 for (i = 0; i < na; ++i) {
9657 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9658 encode_reflection_type (assembly, type, &buf);
9661 buflen = buf.p - buf.buf;
9662 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9663 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9664 sigbuffer_free (&buf);
9670 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9672 MonoDynamicImage *assembly = sig->module->dynamic_image;
9673 guint32 na = mono_array_length (sig->arguments);
9678 sigbuffer_init (&buf, 32);
9680 sigbuffer_add_value (&buf, 0x06);
9681 for (i = 0; i < na; ++i) {
9682 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9683 encode_reflection_type (assembly, type, &buf);
9686 buflen = buf.p - buf.buf;
9687 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9688 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9689 sigbuffer_free (&buf);
9695 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9697 ReflectionMethodBuilder rmb;
9698 MonoMethodSignature *sig;
9703 sig = dynamic_method_to_signature (mb);
9705 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9708 * Resolve references.
9711 * Every second entry in the refs array is reserved for storing handle_class,
9712 * which is needed by the ldtoken implementation in the JIT.
9714 rmb.nrefs = mb->nrefs;
9715 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9716 for (i = 0; i < mb->nrefs; i += 2) {
9717 MonoClass *handle_class;
9719 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
9721 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9722 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9724 * The referenced DynamicMethod should already be created by the managed
9725 * code, except in the case of circular references. In that case, we store
9726 * method in the refs array, and fix it up later when the referenced
9727 * DynamicMethod is created.
9729 if (method->mhandle) {
9730 ref = method->mhandle;
9732 /* FIXME: GC object stored in unmanaged memory */
9735 /* FIXME: GC object stored in unmanaged memory */
9736 method->referenced_by = g_slist_append (method->referenced_by, mb);
9738 handle_class = mono_defaults.methodhandle_class;
9740 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
9743 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9748 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9749 rmb.refs [i + 1] = handle_class;
9752 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
9754 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9756 /* Fix up refs entries pointing at us */
9757 for (l = mb->referenced_by; l; l = l->next) {
9758 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
9759 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
9762 g_assert (method->mhandle);
9764 data = (gpointer*)wrapper->method_data;
9765 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
9766 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
9767 data [i + 1] = mb->mhandle;
9770 g_slist_free (mb->referenced_by);
9774 /* ilgen is no longer needed */
9779 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
9784 mono_runtime_free_method (
9785 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
9790 * mono_reflection_is_valid_dynamic_token:
9792 * Returns TRUE if token is valid.
9796 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
9798 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
9802 * mono_reflection_lookup_dynamic_token:
9804 * Finish the Builder object pointed to by TOKEN and return the corresponding
9805 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
9806 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
9810 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
9812 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9816 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9819 g_assert_not_reached ();
9825 handle_class = &klass;
9826 return resolve_object (image, obj, handle_class, context);
9830 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
9832 gpointer result = NULL;
9834 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9835 result = mono_string_intern ((MonoString*)obj);
9836 *handle_class = NULL;
9838 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9839 MonoReflectionType *tb = (MonoReflectionType*)obj;
9841 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
9842 result = mono_class_from_mono_type (inflated);
9843 mono_metadata_free_type (inflated);
9845 result = mono_class_from_mono_type (tb->type);
9847 *handle_class = mono_defaults.typehandle_class;
9849 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9850 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9851 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9852 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9853 result = ((MonoReflectionMethod*)obj)->method;
9854 result = mono_class_inflate_generic_method (result, context);
9855 *handle_class = mono_defaults.methodhandle_class;
9857 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9858 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9859 result = mb->mhandle;
9861 /* Type is not yet created */
9862 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9864 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9867 * Hopefully this has been filled in by calling CreateType() on the
9871 * TODO: This won't work if the application finishes another
9872 * TypeBuilder instance instead of this one.
9874 result = mb->mhandle;
9876 result = mono_class_inflate_generic_method (result, context);
9877 *handle_class = mono_defaults.methodhandle_class;
9878 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9879 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9881 result = cb->mhandle;
9883 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9885 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9886 result = cb->mhandle;
9888 result = mono_class_inflate_generic_method (result, context);
9889 *handle_class = mono_defaults.methodhandle_class;
9890 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9891 result = ((MonoReflectionField*)obj)->field;
9892 *handle_class = mono_defaults.fieldhandle_class;
9894 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9895 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9896 result = fb->handle;
9899 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9901 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9902 result = fb->handle;
9905 if (fb->handle && fb->handle->parent->generic_container) {
9906 MonoClass *klass = fb->handle->parent;
9907 MonoClass *inflated = mono_class_from_mono_type (mono_class_inflate_generic_type (&klass->byval_arg, context));
9909 result = mono_class_get_field_from_name (inflated, fb->handle->name);
9912 *handle_class = mono_defaults.fieldhandle_class;
9913 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9914 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9917 klass = tb->type.type->data.klass;
9918 if (klass->wastypebuilder) {
9919 /* Already created */
9923 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9924 result = tb->type.type->data.klass;
9927 *handle_class = mono_defaults.typehandle_class;
9928 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9929 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9930 MonoMethodSignature *sig;
9933 if (helper->arguments)
9934 nargs = mono_array_length (helper->arguments);
9938 sig = mono_metadata_signature_alloc (image, nargs);
9939 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9940 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9942 if (helper->call_conv == 0) /* unmanaged */
9943 sig->call_convention = helper->unmanaged_call_conv - 1;
9945 if (helper->call_conv & 0x02)
9946 sig->call_convention = MONO_CALL_VARARG;
9948 sig->call_convention = MONO_CALL_DEFAULT;
9950 sig->param_count = nargs;
9951 /* TODO: Copy type ? */
9952 sig->ret = helper->return_type->type;
9953 for (i = 0; i < nargs; ++i) {
9954 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9955 sig->params [i] = rt->type;
9959 *handle_class = NULL;
9960 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9961 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9962 /* Already created by the managed code */
9963 g_assert (method->mhandle);
9964 result = method->mhandle;
9965 *handle_class = mono_defaults.methodhandle_class;
9966 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
9967 MonoReflectionType *tb = (MonoReflectionType*)obj;
9968 result = mono_class_from_mono_type (mono_class_inflate_generic_type (tb->type, context));
9969 *handle_class = mono_defaults.typehandle_class;
9971 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
9972 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
9973 result = mono_class_from_mono_type (mono_class_inflate_generic_type (ref->type.type, context));
9974 *handle_class = mono_defaults.typehandle_class;
9976 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
9977 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
9978 MonoClass *inflated = mono_class_from_mono_type (f->inst->type.type);
9980 g_assert (f->fb->handle);
9981 result = mono_class_get_field_from_name (inflated, f->fb->handle->name);
9983 *handle_class = mono_defaults.fieldhandle_class;
9985 g_print (obj->vtable->klass->name);
9986 g_assert_not_reached ();
9992 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9993 const static guint32 declsec_flags_map[] = {
9994 0x00000000, /* empty */
9995 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9996 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9997 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9998 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9999 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10000 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10001 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10002 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10003 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10004 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10005 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10006 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10007 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10008 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10009 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10010 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10011 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10012 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10016 * Returns flags that includes all available security action associated to the handle.
10017 * @token: metadata token (either for a class or a method)
10018 * @image: image where resides the metadata.
10021 mono_declsec_get_flags (MonoImage *image, guint32 token)
10023 int index = mono_metadata_declsec_from_index (image, token);
10024 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10025 guint32 result = 0;
10029 /* HasSecurity can be present for other, not specially encoded, attributes,
10030 e.g. SuppressUnmanagedCodeSecurityAttribute */
10034 for (i = index; i < t->rows; i++) {
10035 guint32 cols [MONO_DECL_SECURITY_SIZE];
10037 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10038 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10041 action = cols [MONO_DECL_SECURITY_ACTION];
10042 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10043 result |= declsec_flags_map [action];
10045 g_assert_not_reached ();
10052 * Get the security actions (in the form of flags) associated with the specified method.
10054 * @method: The method for which we want the declarative security flags.
10055 * Return the declarative security flags for the method (only).
10057 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10058 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10061 mono_declsec_flags_from_method (MonoMethod *method)
10063 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10064 /* FIXME: No cache (for the moment) */
10065 guint32 idx = mono_method_get_index (method);
10066 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10067 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10068 return mono_declsec_get_flags (method->klass->image, idx);
10074 * Get the security actions (in the form of flags) associated with the specified class.
10076 * @klass: The class for which we want the declarative security flags.
10077 * Return the declarative security flags for the class.
10079 * Note: We cache the flags inside the MonoClass structure as this will get
10080 * called very often (at least for each method).
10083 mono_declsec_flags_from_class (MonoClass *klass)
10085 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10086 if (!klass->declsec_flags) {
10087 guint32 idx = mono_metadata_token_index (klass->type_token);
10088 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10089 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10090 /* we cache the flags on classes */
10091 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10093 return klass->declsec_flags;
10099 * Get the security actions (in the form of flags) associated with the specified assembly.
10101 * @assembly: The assembly for which we want the declarative security flags.
10102 * Return the declarative security flags for the assembly.
10105 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10107 guint32 idx = 1; /* there is only one assembly */
10108 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10109 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10110 return mono_declsec_get_flags (assembly->image, idx);
10115 * Fill actions for the specific index (which may either be an encoded class token or
10116 * an encoded method token) from the metadata image.
10117 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10120 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10121 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10123 MonoBoolean result = FALSE;
10125 guint32 cols [MONO_DECL_SECURITY_SIZE];
10126 int index = mono_metadata_declsec_from_index (image, token);
10129 t = &image->tables [MONO_TABLE_DECLSECURITY];
10130 for (i = index; i < t->rows; i++) {
10131 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10133 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10136 /* if present only replace (class) permissions with method permissions */
10137 /* if empty accept either class or method permissions */
10138 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10139 if (!actions->demand.blob) {
10140 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10141 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10142 actions->demand.blob = (char*) (blob + 2);
10143 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10146 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10147 if (!actions->noncasdemand.blob) {
10148 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10149 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10150 actions->noncasdemand.blob = (char*) (blob + 2);
10151 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10154 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10155 if (!actions->demandchoice.blob) {
10156 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10157 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10158 actions->demandchoice.blob = (char*) (blob + 2);
10159 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10169 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
10170 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10172 guint32 idx = mono_metadata_token_index (klass->type_token);
10173 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10174 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10175 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
10179 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
10180 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10182 guint32 idx = mono_method_get_index (method);
10183 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10184 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10185 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10189 * Collect all actions (that requires to generate code in mini) assigned for
10190 * the specified method.
10191 * Note: Don't use the content of actions if the function return FALSE.
10194 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10196 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
10197 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10198 MonoBoolean result = FALSE;
10201 /* quick exit if no declarative security is present in the metadata */
10202 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10205 /* we want the original as the wrapper is "free" of the security informations */
10206 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10207 method = mono_marshal_method_from_wrapper (method);
10212 /* First we look for method-level attributes */
10213 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10214 mono_class_init (method->klass);
10215 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10217 result = mono_declsec_get_method_demands_params (method, demands,
10218 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10221 /* Here we use (or create) the class declarative cache to look for demands */
10222 flags = mono_declsec_flags_from_class (method->klass);
10223 if (flags & mask) {
10225 mono_class_init (method->klass);
10226 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10228 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10229 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10232 /* The boolean return value is used as a shortcut in case nothing needs to
10233 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10239 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10241 * Note: Don't use the content of actions if the function return FALSE.
10244 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10246 MonoBoolean result = FALSE;
10249 /* quick exit if no declarative security is present in the metadata */
10250 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10253 /* we want the original as the wrapper is "free" of the security informations */
10254 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10255 method = mono_marshal_method_from_wrapper (method);
10260 /* results are independant - zeroize both */
10261 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10262 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10264 /* First we look for method-level attributes */
10265 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10266 mono_class_init (method->klass);
10268 result = mono_declsec_get_method_demands_params (method, cmethod,
10269 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10272 /* Here we use (or create) the class declarative cache to look for demands */
10273 flags = mono_declsec_flags_from_class (method->klass);
10274 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10275 mono_class_init (method->klass);
10277 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10278 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10285 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10287 * @klass The inherited class - this is the class that provides the security check (attributes)
10289 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10291 * Note: Don't use the content of actions if the function return FALSE.
10294 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10296 MonoBoolean result = FALSE;
10299 /* quick exit if no declarative security is present in the metadata */
10300 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10303 /* Here we use (or create) the class declarative cache to look for demands */
10304 flags = mono_declsec_flags_from_class (klass);
10305 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10306 mono_class_init (klass);
10307 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10309 result |= mono_declsec_get_class_demands_params (klass, demands,
10310 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10317 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10319 * Note: Don't use the content of actions if the function return FALSE.
10322 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10324 /* quick exit if no declarative security is present in the metadata */
10325 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10328 /* we want the original as the wrapper is "free" of the security informations */
10329 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10330 method = mono_marshal_method_from_wrapper (method);
10335 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10336 mono_class_init (method->klass);
10337 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10339 return mono_declsec_get_method_demands_params (method, demands,
10340 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10347 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10349 guint32 cols [MONO_DECL_SECURITY_SIZE];
10353 int index = mono_metadata_declsec_from_index (image, token);
10357 t = &image->tables [MONO_TABLE_DECLSECURITY];
10358 for (i = index; i < t->rows; i++) {
10359 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10361 /* shortcut - index are ordered */
10362 if (token != cols [MONO_DECL_SECURITY_PARENT])
10365 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10366 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10367 entry->blob = (char*) (metadata + 2);
10368 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10377 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10379 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10380 guint32 idx = mono_method_get_index (method);
10381 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10382 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10383 return get_declsec_action (method->klass->image, idx, action, entry);
10389 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10392 guint32 flags = mono_declsec_flags_from_class (klass);
10393 if (declsec_flags_map [action] & flags) {
10394 guint32 idx = mono_metadata_token_index (klass->type_token);
10395 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10396 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10397 return get_declsec_action (klass->image, idx, action, entry);
10403 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10405 guint32 idx = 1; /* there is only one assembly */
10406 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10407 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10409 return get_declsec_action (assembly->image, idx, action, entry);
10413 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10415 MonoObject *res, *exc;
10417 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10418 static MonoMethod *method = NULL;
10420 if (!System_Reflection_Emit_TypeBuilder) {
10421 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10422 g_assert (System_Reflection_Emit_TypeBuilder);
10424 if (method == NULL) {
10425 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10430 * The result of mono_type_get_object () might be a System.MonoType but we
10431 * need a TypeBuilder so use klass->reflection_info.
10433 g_assert (klass->reflection_info);
10434 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10436 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10438 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10442 return *(MonoBoolean*)mono_object_unbox (res);