2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include <mono/metadata/profiler-private.h>
16 #include "mono/metadata/class-internals.h"
17 #include "mono/metadata/gc-internal.h"
18 #include "mono/metadata/tokentype.h"
19 #include "mono/metadata/domain-internals.h"
20 #include "mono/metadata/opcodes.h"
21 #include "mono/metadata/assembly.h"
22 #include "mono/metadata/object-internals.h"
23 #include <mono/metadata/exception.h>
24 #include <mono/metadata/marshal.h>
25 #include <mono/metadata/security-manager.h>
34 #include "rawbuffer.h"
35 #include "mono-endian.h"
36 #include <mono/metadata/gc-internal.h>
44 #define TEXT_OFFSET 512
45 #define CLI_H_SIZE 136
46 #define FILE_ALIGN 512
47 #define VIRT_ALIGN 8192
48 #define START_TEXT_RVA 0x00002000
51 MonoReflectionILGen *ilgen;
52 MonoReflectionType *rtype;
53 MonoArray *parameters;
54 MonoArray *generic_params;
55 MonoGenericContainer *generic_container;
61 guint32 *table_idx; /* note: it's a pointer */
65 MonoBoolean init_locals;
66 MonoBoolean skip_visibility;
67 MonoArray *return_modreq;
68 MonoArray *return_modopt;
69 MonoArray *param_modreq;
70 MonoArray *param_modopt;
71 MonoArray *permissions;
76 int charset, extra_flags, native_cc;
77 MonoString *dll, *dllentry;
78 } ReflectionMethodBuilder;
82 MonoReflectionGenericParam *gparam;
83 } GenericParamTableEntry;
85 const unsigned char table_sizes [MONO_TABLE_NUM] = {
95 MONO_INTERFACEIMPL_SIZE,
96 MONO_MEMBERREF_SIZE, /* 0x0A */
98 MONO_CUSTOM_ATTR_SIZE,
99 MONO_FIELD_MARSHAL_SIZE,
100 MONO_DECL_SECURITY_SIZE,
101 MONO_CLASS_LAYOUT_SIZE,
102 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
103 MONO_STAND_ALONE_SIGNATURE_SIZE,
107 MONO_PROPERTY_MAP_SIZE,
110 MONO_METHOD_SEMA_SIZE,
111 MONO_METHODIMPL_SIZE,
112 MONO_MODULEREF_SIZE, /* 0x1A */
118 MONO_ASSEMBLY_SIZE, /* 0x20 */
119 MONO_ASSEMBLY_PROCESSOR_SIZE,
120 MONO_ASSEMBLYOS_SIZE,
121 MONO_ASSEMBLYREF_SIZE,
122 MONO_ASSEMBLYREFPROC_SIZE,
123 MONO_ASSEMBLYREFOS_SIZE,
127 MONO_NESTED_CLASS_SIZE,
129 MONO_GENERICPARAM_SIZE, /* 0x2A */
130 MONO_METHODSPEC_SIZE,
131 MONO_GENPARCONSTRAINT_SIZE
135 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
136 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
137 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
138 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
139 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
140 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
141 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
142 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
143 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
144 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
145 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
146 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
147 static void ensure_runtime_vtable (MonoClass *klass);
148 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
149 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
150 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
151 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
152 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
153 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
155 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
156 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
157 static CRITICAL_SECTION reflection_mutex;
160 mono_reflection_init (void)
162 InitializeCriticalSection (&reflection_mutex);
166 sigbuffer_init (SigBuffer *buf, int size)
168 buf->buf = g_malloc (size);
170 buf->end = buf->buf + size;
174 sigbuffer_make_room (SigBuffer *buf, int size)
176 if (buf->end - buf->p < size) {
177 int new_size = buf->end - buf->buf + size + 32;
178 char *p = g_realloc (buf->buf, new_size);
179 size = buf->p - buf->buf;
182 buf->end = buf->buf + new_size;
187 sigbuffer_add_value (SigBuffer *buf, guint32 val)
189 sigbuffer_make_room (buf, 6);
190 mono_metadata_encode_value (val, buf->p, &buf->p);
194 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
196 sigbuffer_make_room (buf, 1);
202 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
204 sigbuffer_make_room (buf, size);
205 memcpy (buf->p, p, size);
210 sigbuffer_free (SigBuffer *buf)
218 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
222 mp_g_malloc (MonoMemPool *mp, guint size)
225 return mono_mempool_alloc (mp, size);
227 return g_malloc (size);
233 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
237 mp_g_malloc0 (MonoMemPool *mp, guint size)
240 return mono_mempool_alloc0 (mp, size);
242 return g_malloc0 (size);
248 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
249 * memory from the C heap.
252 mp_string_to_utf8 (MonoMemPool *mp, MonoString *s)
255 return mono_string_to_utf8_mp (mp, s);
257 return mono_string_to_utf8 (s);
260 #define mp_g_new(mp,struct_type, n_structs) \
261 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
263 #define mp_g_new0(mp,struct_type, n_structs) \
264 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
267 alloc_table (MonoDynamicTable *table, guint nrows)
270 g_assert (table->columns);
271 if (nrows + 1 >= table->alloc_rows) {
272 while (nrows + 1 >= table->alloc_rows) {
273 if (table->alloc_rows == 0)
274 table->alloc_rows = 16;
276 table->alloc_rows *= 2;
279 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
284 make_room_in_stream (MonoDynamicStream *stream, int size)
286 if (size <= stream->alloc_size)
289 while (stream->alloc_size <= size) {
290 if (stream->alloc_size < 4096)
291 stream->alloc_size = 4096;
293 stream->alloc_size *= 2;
296 stream->data = g_realloc (stream->data, stream->alloc_size);
300 string_heap_insert (MonoDynamicStream *sh, const char *str)
304 gpointer oldkey, oldval;
306 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
307 return GPOINTER_TO_UINT (oldval);
309 len = strlen (str) + 1;
312 make_room_in_stream (sh, idx + len);
315 * We strdup the string even if we already copy them in sh->data
316 * so that the string pointers in the hash remain valid even if
317 * we need to realloc sh->data. We may want to avoid that later.
319 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
320 memcpy (sh->data + idx, str, len);
326 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
328 char *name = mono_string_to_utf8 (str);
330 idx = string_heap_insert (sh, name);
336 string_heap_init (MonoDynamicStream *sh)
339 sh->alloc_size = 4096;
340 sh->data = g_malloc (4096);
341 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
342 string_heap_insert (sh, "");
346 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
350 make_room_in_stream (stream, stream->index + len);
351 memcpy (stream->data + stream->index, data, len);
353 stream->index += len;
355 * align index? Not without adding an additional param that controls it since
356 * we may store a blob value in pieces.
362 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
366 make_room_in_stream (stream, stream->index + len);
367 memset (stream->data + stream->index, 0, len);
369 stream->index += len;
374 stream_data_align (MonoDynamicStream *stream)
377 guint32 count = stream->index % 4;
379 /* we assume the stream data will be aligned */
381 mono_image_add_stream_data (stream, buf, 4 - count);
385 mono_blob_entry_hash (const char* str)
389 len = mono_metadata_decode_blob_size (str, &str);
393 for (str += 1; str < end; str++)
394 h = (h << 5) - h + *str;
402 mono_blob_entry_equal (const char *str1, const char *str2) {
406 len = mono_metadata_decode_blob_size (str1, &end1);
407 len2 = mono_metadata_decode_blob_size (str2, &end2);
410 return memcmp (end1, end2, len) == 0;
414 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
418 gpointer oldkey, oldval;
420 copy = g_malloc (s1+s2);
421 memcpy (copy, b1, s1);
422 memcpy (copy + s1, b2, s2);
423 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
425 idx = GPOINTER_TO_UINT (oldval);
427 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
428 mono_image_add_stream_data (&assembly->blob, b2, s2);
429 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
435 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
439 guint32 size = buf->p - buf->buf;
441 g_assert (size <= (buf->end - buf->buf));
442 mono_metadata_encode_value (size, b, &b);
443 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
447 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
448 * dest may be misaligned.
451 swap_with_size (char *dest, const char* val, int len, int nelem) {
452 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
455 for (elem = 0; elem < nelem; ++elem) {
481 g_assert_not_reached ();
487 memcpy (dest, val, len * nelem);
492 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
496 guint32 idx = 0, len;
498 len = str->length * 2;
499 mono_metadata_encode_value (len, b, &b);
500 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
502 char *swapped = g_malloc (2 * mono_string_length (str));
503 const char *p = (const char*)mono_string_chars (str);
505 swap_with_size (swapped, p, 2, mono_string_length (str));
506 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
510 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
515 /* modified version needed to handle building corlib */
517 my_mono_class_from_mono_type (MonoType *type) {
518 switch (type->type) {
519 case MONO_TYPE_ARRAY:
521 case MONO_TYPE_SZARRAY:
522 case MONO_TYPE_GENERICINST:
523 return mono_class_from_mono_type (type);
526 g_assert (type->data.generic_param->pklass);
527 return type->data.generic_param->pklass;
529 /* should be always valid when we reach this case... */
530 return type->data.klass;
535 default_class_from_mono_type (MonoType *type)
537 switch (type->type) {
538 case MONO_TYPE_OBJECT:
539 return mono_defaults.object_class;
541 return mono_defaults.void_class;
542 case MONO_TYPE_BOOLEAN:
543 return mono_defaults.boolean_class;
545 return mono_defaults.char_class;
547 return mono_defaults.sbyte_class;
549 return mono_defaults.byte_class;
551 return mono_defaults.int16_class;
553 return mono_defaults.uint16_class;
555 return mono_defaults.int32_class;
557 return mono_defaults.uint32_class;
559 return mono_defaults.int_class;
561 return mono_defaults.uint_class;
563 return mono_defaults.int64_class;
565 return mono_defaults.uint64_class;
567 return mono_defaults.single_class;
569 return mono_defaults.double_class;
570 case MONO_TYPE_STRING:
571 return mono_defaults.string_class;
573 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
574 g_assert_not_reached ();
581 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
584 MonoGenericInst *class_inst;
589 class_inst = gclass->context.class_inst;
591 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
592 klass = gclass->container_class;
593 sigbuffer_add_value (buf, klass->byval_arg.type);
594 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
596 sigbuffer_add_value (buf, class_inst->type_argc);
597 for (i = 0; i < class_inst->type_argc; ++i)
598 encode_type (assembly, class_inst->type_argv [i], buf);
603 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
606 g_assert_not_reached ();
611 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
615 case MONO_TYPE_BOOLEAN:
629 case MONO_TYPE_STRING:
630 case MONO_TYPE_OBJECT:
631 case MONO_TYPE_TYPEDBYREF:
632 sigbuffer_add_value (buf, type->type);
635 sigbuffer_add_value (buf, type->type);
636 encode_type (assembly, type->data.type, buf);
638 case MONO_TYPE_SZARRAY:
639 sigbuffer_add_value (buf, type->type);
640 encode_type (assembly, &type->data.klass->byval_arg, buf);
642 case MONO_TYPE_VALUETYPE:
643 case MONO_TYPE_CLASS: {
644 MonoClass *k = mono_class_from_mono_type (type);
646 if (k->generic_container) {
647 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
648 encode_generic_class (assembly, gclass, buf);
651 * Make sure we use the correct type.
653 sigbuffer_add_value (buf, k->byval_arg.type);
655 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
656 * otherwise two typerefs could point to the same type, leading to
657 * verification errors.
659 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
663 case MONO_TYPE_ARRAY:
664 sigbuffer_add_value (buf, type->type);
665 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
666 sigbuffer_add_value (buf, type->data.array->rank);
667 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
668 sigbuffer_add_value (buf, 0);
670 case MONO_TYPE_GENERICINST:
671 encode_generic_class (assembly, type->data.generic_class, buf);
675 sigbuffer_add_value (buf, type->type);
676 sigbuffer_add_value (buf, type->data.generic_param->num);
679 g_error ("need to encode type %x", type->type);
684 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
687 sigbuffer_add_value (buf, MONO_TYPE_VOID);
692 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
693 encode_type (assembly, type->type, buf);
697 g_assert_not_reached ();
702 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
707 for (i = 0; i < mono_array_length (modreq); ++i) {
708 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
709 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
710 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
714 for (i = 0; i < mono_array_length (modopt); ++i) {
715 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
716 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
717 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
723 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
727 guint32 nparams = sig->param_count;
733 sigbuffer_init (&buf, 32);
735 * FIXME: vararg, explicit_this, differenc call_conv values...
737 idx = sig->call_convention;
739 idx |= 0x20; /* hasthis */
740 if (sig->generic_param_count)
741 idx |= 0x10; /* generic */
742 sigbuffer_add_byte (&buf, idx);
743 if (sig->generic_param_count)
744 sigbuffer_add_value (&buf, sig->generic_param_count);
745 sigbuffer_add_value (&buf, nparams);
746 encode_type (assembly, sig->ret, &buf);
747 for (i = 0; i < nparams; ++i) {
748 if (i == sig->sentinelpos)
749 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
750 encode_type (assembly, sig->params [i], &buf);
752 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
753 sigbuffer_free (&buf);
758 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
761 * FIXME: reuse code from method_encode_signature().
765 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
766 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
767 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
770 sigbuffer_init (&buf, 32);
771 /* LAMESPEC: all the call conv spec is foobared */
772 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
773 if (mb->call_conv & 2)
774 idx |= 0x5; /* vararg */
775 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
776 idx |= 0x20; /* hasthis */
778 idx |= 0x10; /* generic */
779 sigbuffer_add_byte (&buf, idx);
781 sigbuffer_add_value (&buf, ngparams);
782 sigbuffer_add_value (&buf, nparams + notypes);
783 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
784 encode_reflection_type (assembly, mb->rtype, &buf);
785 for (i = 0; i < nparams; ++i) {
786 MonoArray *modreq = NULL;
787 MonoArray *modopt = NULL;
788 MonoReflectionType *pt;
790 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
791 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
792 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
793 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
794 encode_custom_modifiers (assembly, modreq, modopt, &buf);
795 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
796 encode_reflection_type (assembly, pt, &buf);
799 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
800 for (i = 0; i < notypes; ++i) {
801 MonoReflectionType *pt;
803 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
804 encode_reflection_type (assembly, pt, &buf);
807 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
808 sigbuffer_free (&buf);
813 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
815 MonoDynamicTable *table;
817 guint32 idx, sig_idx;
818 guint nl = mono_array_length (ilgen->locals);
822 sigbuffer_init (&buf, 32);
823 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
824 idx = table->next_idx ++;
826 alloc_table (table, table->rows);
827 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
829 sigbuffer_add_value (&buf, 0x07);
830 sigbuffer_add_value (&buf, nl);
831 for (i = 0; i < nl; ++i) {
832 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
835 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
837 encode_reflection_type (assembly, lb->type, &buf);
839 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
840 sigbuffer_free (&buf);
842 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
848 method_count_clauses (MonoReflectionILGen *ilgen)
850 guint32 num_clauses = 0;
853 MonoILExceptionInfo *ex_info;
854 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
855 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
856 if (ex_info->handlers)
857 num_clauses += mono_array_length (ex_info->handlers);
865 static MonoExceptionClause*
866 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
868 MonoExceptionClause *clauses;
869 MonoExceptionClause *clause;
870 MonoILExceptionInfo *ex_info;
871 MonoILExceptionBlock *ex_block;
872 guint32 finally_start;
873 int i, j, clause_index;;
875 clauses = g_new0 (MonoExceptionClause, num_clauses);
878 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
879 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
880 finally_start = ex_info->start + ex_info->len;
881 if (!ex_info->handlers)
883 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
884 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
885 clause = &(clauses [clause_index]);
887 clause->flags = ex_block->type;
888 clause->try_offset = ex_info->start;
890 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
891 clause->try_len = finally_start - ex_info->start;
893 clause->try_len = ex_info->len;
894 clause->handler_offset = ex_block->start;
895 clause->handler_len = ex_block->len;
896 if (ex_block->extype) {
897 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
899 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
900 clause->data.filter_offset = ex_block->filter_offset;
902 clause->data.filter_offset = 0;
904 finally_start = ex_block->start + ex_block->len;
914 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
920 gint32 num_locals = 0;
921 gint32 num_exception = 0;
924 char fat_header [12];
927 guint32 local_sig = 0;
928 guint32 header_size = 12;
931 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
932 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
936 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
938 code = mb->ilgen->code;
939 code_size = mb->ilgen->code_len;
940 max_stack = mb->ilgen->max_stack;
941 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
942 if (mb->ilgen->ex_handlers)
943 num_exception = method_count_clauses (mb->ilgen);
947 char *name = mono_string_to_utf8 (mb->name);
948 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
949 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
952 mono_raise_exception (exception);
955 code_size = mono_array_length (code);
956 max_stack = 8; /* we probably need to run a verifier on the code... */
959 stream_data_align (&assembly->code);
961 /* check for exceptions, maxstack, locals */
962 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
964 if (code_size < 64 && !(code_size & 1)) {
965 flags = (code_size << 2) | 0x2;
966 } else if (code_size < 32 && (code_size & 1)) {
967 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
971 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
972 /* add to the fixup todo list */
973 if (mb->ilgen && mb->ilgen->num_token_fixups)
974 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
975 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
976 return assembly->text_rva + idx;
980 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
982 * FIXME: need to set also the header size in fat_flags.
983 * (and more sects and init locals flags)
987 fat_flags |= METHOD_HEADER_MORE_SECTS;
989 fat_flags |= METHOD_HEADER_INIT_LOCALS;
990 fat_header [0] = fat_flags;
991 fat_header [1] = (header_size / 4 ) << 4;
992 short_value = GUINT16_TO_LE (max_stack);
993 memcpy (fat_header + 2, &short_value, 2);
994 int_value = GUINT32_TO_LE (code_size);
995 memcpy (fat_header + 4, &int_value, 4);
996 int_value = GUINT32_TO_LE (local_sig);
997 memcpy (fat_header + 8, &int_value, 4);
998 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
999 /* add to the fixup todo list */
1000 if (mb->ilgen && mb->ilgen->num_token_fixups)
1001 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1003 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1004 if (num_exception) {
1005 unsigned char sheader [4];
1006 MonoILExceptionInfo * ex_info;
1007 MonoILExceptionBlock * ex_block;
1010 stream_data_align (&assembly->code);
1011 /* always use fat format for now */
1012 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1013 num_exception *= 6 * sizeof (guint32);
1014 num_exception += 4; /* include the size of the header */
1015 sheader [1] = num_exception & 0xff;
1016 sheader [2] = (num_exception >> 8) & 0xff;
1017 sheader [3] = (num_exception >> 16) & 0xff;
1018 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1019 /* fat header, so we are already aligned */
1021 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1022 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1023 if (ex_info->handlers) {
1024 int finally_start = ex_info->start + ex_info->len;
1025 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1027 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1029 val = GUINT32_TO_LE (ex_block->type);
1030 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1032 val = GUINT32_TO_LE (ex_info->start);
1033 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1034 /* need fault, too, probably */
1035 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1036 val = GUINT32_TO_LE (finally_start - ex_info->start);
1038 val = GUINT32_TO_LE (ex_info->len);
1039 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1040 /* handler offset */
1041 val = GUINT32_TO_LE (ex_block->start);
1042 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1044 val = GUINT32_TO_LE (ex_block->len);
1045 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1046 finally_start = ex_block->start + ex_block->len;
1047 if (ex_block->extype) {
1048 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1050 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1051 val = ex_block->filter_offset;
1055 val = GUINT32_TO_LE (val);
1056 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1057 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1058 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1061 g_error ("No clauses for ex info block %d", i);
1065 return assembly->text_rva + idx;
1069 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1072 MonoDynamicTable *table;
1075 table = &assembly->tables [table_idx];
1077 g_assert (col < table->columns);
1079 values = table->values + table->columns;
1080 for (i = 1; i <= table->rows; ++i) {
1081 if (values [col] == token)
1083 values += table->columns;
1088 /* protected by reflection_mutex:
1089 * maps a mono runtime reflection handle to MonoCustomAttrInfo*
1091 static GHashTable *dynamic_custom_attrs = NULL;
1093 static MonoCustomAttrInfo*
1094 lookup_custom_attr (void *member)
1096 MonoCustomAttrInfo *ainfo, *res;
1099 mono_reflection_lock ();
1100 ainfo = g_hash_table_lookup (dynamic_custom_attrs, member);
1101 mono_reflection_unlock ();
1104 /* Need to copy since it will be freed later */
1105 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
1106 res = g_malloc0 (size);
1107 memcpy (res, ainfo, size);
1114 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1116 /* FIXME: Need to do more checks */
1117 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1118 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1120 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1127 static MonoCustomAttrInfo*
1128 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1130 int i, index, count, not_visible;
1131 MonoCustomAttrInfo *ainfo;
1132 MonoReflectionCustomAttr *cattr;
1136 /* FIXME: check in assembly the Run flag is set */
1138 count = mono_array_length (cattrs);
1140 /* Skip nonpublic attributes since MS.NET seems to do the same */
1141 /* FIXME: This needs to be done more globally */
1143 for (i = 0; i < count; ++i) {
1144 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1145 if (!custom_attr_visible (image, cattr))
1148 count -= not_visible;
1150 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1152 ainfo->image = image;
1153 ainfo->num_attrs = count;
1155 mono_loader_lock ();
1156 for (i = 0; i < count; ++i) {
1157 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1158 if (custom_attr_visible (image, cattr)) {
1159 unsigned char *saved = mono_mempool_alloc (image->mempool, mono_array_length (cattr->data));
1160 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1161 ainfo->attrs [index].ctor = cattr->ctor->method;
1162 ainfo->attrs [index].data = saved;
1163 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1167 mono_loader_unlock ();
1173 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1175 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1180 mono_reflection_lock ();
1181 if (!dynamic_custom_attrs)
1182 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1184 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1185 ainfo->cached = TRUE;
1186 mono_reflection_unlock ();
1190 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1197 * idx is the table index of the object
1198 * type is one of MONO_CUSTOM_ATTR_*
1201 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1203 MonoDynamicTable *table;
1204 MonoReflectionCustomAttr *cattr;
1206 guint32 count, i, token;
1208 char *p = blob_size;
1210 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1213 count = mono_array_length (cattrs);
1214 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1215 table->rows += count;
1216 alloc_table (table, table->rows);
1217 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1218 idx <<= MONO_CUSTOM_ATTR_BITS;
1220 for (i = 0; i < count; ++i) {
1221 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1222 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1223 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1224 type = mono_metadata_token_index (token);
1225 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1226 switch (mono_metadata_token_table (token)) {
1227 case MONO_TABLE_METHOD:
1228 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1230 case MONO_TABLE_MEMBERREF:
1231 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1234 g_warning ("got wrong token in custom attr");
1237 values [MONO_CUSTOM_ATTR_TYPE] = type;
1239 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1240 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1241 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1242 values += MONO_CUSTOM_ATTR_SIZE;
1248 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1250 MonoDynamicTable *table;
1252 guint32 count, i, idx;
1253 MonoReflectionPermissionSet *perm;
1258 count = mono_array_length (permissions);
1259 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1260 table->rows += count;
1261 alloc_table (table, table->rows);
1263 for (i = 0; i < mono_array_length (permissions); ++i) {
1264 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1266 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1268 idx = mono_metadata_token_index (parent_token);
1269 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1270 switch (mono_metadata_token_table (parent_token)) {
1271 case MONO_TABLE_TYPEDEF:
1272 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1274 case MONO_TABLE_METHOD:
1275 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1277 case MONO_TABLE_ASSEMBLY:
1278 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1281 g_assert_not_reached ();
1284 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1285 values [MONO_DECL_SECURITY_PARENT] = idx;
1286 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1293 * Fill in the MethodDef and ParamDef tables for a method.
1294 * This is used for both normal methods and constructors.
1297 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1299 MonoDynamicTable *table;
1303 /* room in this table is already allocated */
1304 table = &assembly->tables [MONO_TABLE_METHOD];
1305 *mb->table_idx = table->next_idx ++;
1306 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1307 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1308 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1309 values [MONO_METHOD_FLAGS] = mb->attrs;
1310 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1311 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1312 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1314 table = &assembly->tables [MONO_TABLE_PARAM];
1315 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1317 mono_image_add_decl_security (assembly,
1318 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1321 MonoDynamicTable *mtable;
1324 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1325 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1328 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1329 if (mono_array_get (mb->pinfo, gpointer, i))
1332 table->rows += count;
1333 alloc_table (table, table->rows);
1334 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1335 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1336 MonoReflectionParamBuilder *pb;
1337 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1338 values [MONO_PARAM_FLAGS] = pb->attrs;
1339 values [MONO_PARAM_SEQUENCE] = i;
1340 if (pb->name != NULL) {
1341 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1343 values [MONO_PARAM_NAME] = 0;
1345 values += MONO_PARAM_SIZE;
1346 if (pb->marshal_info) {
1348 alloc_table (mtable, mtable->rows);
1349 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1350 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1351 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1353 pb->table_idx = table->next_idx++;
1354 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1355 guint32 field_type = 0;
1356 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1358 alloc_table (mtable, mtable->rows);
1359 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1360 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1361 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1362 mvalues [MONO_CONSTANT_TYPE] = field_type;
1363 mvalues [MONO_CONSTANT_PADDING] = 0;
1371 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1373 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1375 rmb->ilgen = mb->ilgen;
1376 rmb->rtype = mb->rtype;
1377 rmb->parameters = mb->parameters;
1378 rmb->generic_params = mb->generic_params;
1379 rmb->generic_container = mb->generic_container;
1380 rmb->opt_types = NULL;
1381 rmb->pinfo = mb->pinfo;
1382 rmb->attrs = mb->attrs;
1383 rmb->iattrs = mb->iattrs;
1384 rmb->call_conv = mb->call_conv;
1385 rmb->code = mb->code;
1386 rmb->type = mb->type;
1387 rmb->name = mb->name;
1388 rmb->table_idx = &mb->table_idx;
1389 rmb->init_locals = mb->init_locals;
1390 rmb->skip_visibility = FALSE;
1391 rmb->return_modreq = mb->return_modreq;
1392 rmb->return_modopt = mb->return_modopt;
1393 rmb->param_modreq = mb->param_modreq;
1394 rmb->param_modopt = mb->param_modopt;
1395 rmb->permissions = mb->permissions;
1396 rmb->mhandle = mb->mhandle;
1401 rmb->charset = mb->charset;
1402 rmb->extra_flags = mb->extra_flags;
1403 rmb->native_cc = mb->native_cc;
1404 rmb->dllentry = mb->dllentry;
1410 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1412 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1414 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1416 rmb->ilgen = mb->ilgen;
1417 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1418 rmb->parameters = mb->parameters;
1419 rmb->generic_params = NULL;
1420 rmb->generic_container = NULL;
1421 rmb->opt_types = NULL;
1422 rmb->pinfo = mb->pinfo;
1423 rmb->attrs = mb->attrs;
1424 rmb->iattrs = mb->iattrs;
1425 rmb->call_conv = mb->call_conv;
1427 rmb->type = mb->type;
1428 rmb->name = mono_string_new (mono_domain_get (), name);
1429 rmb->table_idx = &mb->table_idx;
1430 rmb->init_locals = mb->init_locals;
1431 rmb->skip_visibility = FALSE;
1432 rmb->return_modreq = NULL;
1433 rmb->return_modopt = NULL;
1434 rmb->param_modreq = mb->param_modreq;
1435 rmb->param_modopt = mb->param_modopt;
1436 rmb->permissions = mb->permissions;
1437 rmb->mhandle = mb->mhandle;
1443 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1445 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1447 rmb->ilgen = mb->ilgen;
1448 rmb->rtype = mb->rtype;
1449 rmb->parameters = mb->parameters;
1450 rmb->generic_params = NULL;
1451 rmb->generic_container = NULL;
1452 rmb->opt_types = NULL;
1454 rmb->attrs = mb->attrs;
1456 rmb->call_conv = mb->call_conv;
1458 rmb->type = (MonoObject *) mb->owner;
1459 rmb->name = mb->name;
1460 rmb->table_idx = NULL;
1461 rmb->init_locals = mb->init_locals;
1462 rmb->skip_visibility = mb->skip_visibility;
1463 rmb->return_modreq = NULL;
1464 rmb->return_modopt = NULL;
1465 rmb->param_modreq = NULL;
1466 rmb->param_modopt = NULL;
1467 rmb->permissions = NULL;
1468 rmb->mhandle = mb->mhandle;
1474 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1476 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1477 MonoDynamicTable *table;
1481 if (!mb->override_method)
1484 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1486 alloc_table (table, table->rows);
1487 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1488 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1489 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1491 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1492 switch (mono_metadata_token_table (tok)) {
1493 case MONO_TABLE_MEMBERREF:
1494 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1496 case MONO_TABLE_METHOD:
1497 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1500 g_assert_not_reached ();
1502 values [MONO_METHODIMPL_DECLARATION] = tok;
1506 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1508 MonoDynamicTable *table;
1510 ReflectionMethodBuilder rmb;
1513 reflection_methodbuilder_from_method_builder (&rmb, mb);
1515 mono_image_basic_method (&rmb, assembly);
1516 mb->table_idx = *rmb.table_idx;
1518 if (mb->dll) { /* It's a P/Invoke method */
1520 /* map CharSet values to on-disk values */
1521 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1522 int extra_flags = mb->extra_flags;
1523 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1525 alloc_table (table, table->rows);
1526 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1528 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1529 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1531 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1533 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1534 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1535 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1536 table = &assembly->tables [MONO_TABLE_MODULEREF];
1538 alloc_table (table, table->rows);
1539 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1540 values [MONO_IMPLMAP_SCOPE] = table->rows;
1544 if (mb->generic_params) {
1545 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1546 table->rows += mono_array_length (mb->generic_params);
1547 alloc_table (table, table->rows);
1548 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1549 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1551 mono_image_get_generic_param_info (
1552 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1559 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1561 ReflectionMethodBuilder rmb;
1563 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1565 mono_image_basic_method (&rmb, assembly);
1566 mb->table_idx = *rmb.table_idx;
1570 type_get_fully_qualified_name (MonoType *type)
1572 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1576 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1580 klass = my_mono_class_from_mono_type (type);
1582 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1583 ta = klass->image->assembly;
1584 if (ta->dynamic || (ta == ass)) {
1585 if (klass->generic_class)
1586 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1588 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1591 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1595 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1600 if (!assembly->save)
1603 sigbuffer_init (&buf, 32);
1605 sigbuffer_add_value (&buf, 0x06);
1606 /* encode custom attributes before the type */
1607 encode_type (assembly, type, &buf);
1608 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1609 sigbuffer_free (&buf);
1614 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1619 sigbuffer_init (&buf, 32);
1621 sigbuffer_add_value (&buf, 0x06);
1622 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1623 /* encode custom attributes before the type */
1624 encode_reflection_type (assembly, fb->type, &buf);
1625 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1626 sigbuffer_free (&buf);
1631 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1632 char blob_size [64];
1633 char *b = blob_size;
1636 guint32 idx = 0, len = 0, dummy = 0;
1638 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1639 guint32 fpa_double [2];
1644 p = buf = g_malloc (64);
1646 *ret_type = MONO_TYPE_CLASS;
1648 box_val = (char*)&dummy;
1650 box_val = ((char*)val) + sizeof (MonoObject);
1651 *ret_type = val->vtable->klass->byval_arg.type;
1654 switch (*ret_type) {
1655 case MONO_TYPE_BOOLEAN:
1660 case MONO_TYPE_CHAR:
1677 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1678 fpa_p = (guint32*)box_val;
1679 fpa_double [0] = fpa_p [1];
1680 fpa_double [1] = fpa_p [0];
1681 box_val = (char*)fpa_double;
1685 case MONO_TYPE_VALUETYPE:
1686 if (val->vtable->klass->enumtype) {
1687 *ret_type = val->vtable->klass->enum_basetype->type;
1690 g_error ("we can't encode valuetypes");
1691 case MONO_TYPE_CLASS:
1693 case MONO_TYPE_STRING: {
1694 MonoString *str = (MonoString*)val;
1695 /* there is no signature */
1696 len = str->length * 2;
1697 mono_metadata_encode_value (len, b, &b);
1698 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1700 char *swapped = g_malloc (2 * mono_string_length (str));
1701 const char *p = (const char*)mono_string_chars (str);
1703 swap_with_size (swapped, p, 2, mono_string_length (str));
1704 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1708 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1714 case MONO_TYPE_GENERICINST:
1715 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1718 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1721 /* there is no signature */
1722 mono_metadata_encode_value (len, b, &b);
1723 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1724 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1725 swap_with_size (blob_size, box_val, len, 1);
1726 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1728 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1736 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1741 sigbuffer_init (&buf, 32);
1743 sigbuffer_add_value (&buf, minfo->type);
1745 switch (minfo->type) {
1746 case MONO_NATIVE_BYVALTSTR:
1747 case MONO_NATIVE_BYVALARRAY:
1748 sigbuffer_add_value (&buf, minfo->count);
1750 case MONO_NATIVE_LPARRAY:
1751 if (minfo->eltype || minfo->has_size) {
1752 sigbuffer_add_value (&buf, minfo->eltype);
1753 if (minfo->has_size) {
1754 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1755 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1757 /* LAMESPEC: ElemMult is undocumented */
1758 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1762 case MONO_NATIVE_CUSTOM:
1764 str = mono_string_to_utf8 (minfo->guid);
1766 sigbuffer_add_value (&buf, len);
1767 sigbuffer_add_mem (&buf, str, len);
1770 sigbuffer_add_value (&buf, 0);
1772 /* native type name */
1773 sigbuffer_add_value (&buf, 0);
1774 /* custom marshaler type name */
1775 if (minfo->marshaltype || minfo->marshaltyperef) {
1776 if (minfo->marshaltyperef)
1777 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1779 str = mono_string_to_utf8 (minfo->marshaltype);
1781 sigbuffer_add_value (&buf, len);
1782 sigbuffer_add_mem (&buf, str, len);
1785 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1786 sigbuffer_add_value (&buf, 0);
1788 if (minfo->mcookie) {
1789 str = mono_string_to_utf8 (minfo->mcookie);
1791 sigbuffer_add_value (&buf, len);
1792 sigbuffer_add_mem (&buf, str, len);
1795 sigbuffer_add_value (&buf, 0);
1801 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1802 sigbuffer_free (&buf);
1807 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1809 MonoDynamicTable *table;
1812 /* maybe this fixup should be done in the C# code */
1813 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1814 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1815 table = &assembly->tables [MONO_TABLE_FIELD];
1816 fb->table_idx = table->next_idx ++;
1817 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1818 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1819 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1820 values [MONO_FIELD_FLAGS] = fb->attrs;
1821 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1823 if (fb->offset != -1) {
1824 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1826 alloc_table (table, table->rows);
1827 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1828 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1829 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1831 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1832 guint32 field_type = 0;
1833 table = &assembly->tables [MONO_TABLE_CONSTANT];
1835 alloc_table (table, table->rows);
1836 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1837 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1838 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1839 values [MONO_CONSTANT_TYPE] = field_type;
1840 values [MONO_CONSTANT_PADDING] = 0;
1842 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1844 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1846 alloc_table (table, table->rows);
1847 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1848 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1850 * We store it in the code section because it's simpler for now.
1853 if (mono_array_length (fb->rva_data) >= 10)
1854 stream_data_align (&assembly->code);
1855 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1857 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1858 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1860 if (fb->marshal_info) {
1861 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1863 alloc_table (table, table->rows);
1864 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1865 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1866 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1871 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1874 guint32 nparams = 0;
1875 MonoReflectionMethodBuilder *mb = fb->get_method;
1876 MonoReflectionMethodBuilder *smb = fb->set_method;
1879 if (mb && mb->parameters)
1880 nparams = mono_array_length (mb->parameters);
1881 if (!mb && smb && smb->parameters)
1882 nparams = mono_array_length (smb->parameters) - 1;
1883 sigbuffer_init (&buf, 32);
1884 sigbuffer_add_byte (&buf, 0x08);
1885 sigbuffer_add_value (&buf, nparams);
1887 encode_reflection_type (assembly, mb->rtype, &buf);
1888 for (i = 0; i < nparams; ++i) {
1889 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1890 encode_reflection_type (assembly, pt, &buf);
1892 } else if (smb && smb->parameters) {
1893 /* the property type is the last param */
1894 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1895 for (i = 0; i < nparams; ++i) {
1896 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1897 encode_reflection_type (assembly, pt, &buf);
1900 encode_reflection_type (assembly, fb->type, &buf);
1903 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1904 sigbuffer_free (&buf);
1909 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1911 MonoDynamicTable *table;
1913 guint num_methods = 0;
1917 * we need to set things in the following tables:
1918 * PROPERTYMAP (info already filled in _get_type_info ())
1919 * PROPERTY (rows already preallocated in _get_type_info ())
1920 * METHOD (method info already done with the generic method code)
1923 table = &assembly->tables [MONO_TABLE_PROPERTY];
1924 pb->table_idx = table->next_idx ++;
1925 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1926 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1927 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1928 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1930 /* FIXME: we still don't handle 'other' methods */
1931 if (pb->get_method) num_methods ++;
1932 if (pb->set_method) num_methods ++;
1934 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1935 table->rows += num_methods;
1936 alloc_table (table, table->rows);
1938 if (pb->get_method) {
1939 semaidx = table->next_idx ++;
1940 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1941 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1942 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1943 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1945 if (pb->set_method) {
1946 semaidx = table->next_idx ++;
1947 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1948 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1949 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1950 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1955 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1957 MonoDynamicTable *table;
1959 guint num_methods = 0;
1963 * we need to set things in the following tables:
1964 * EVENTMAP (info already filled in _get_type_info ())
1965 * EVENT (rows already preallocated in _get_type_info ())
1966 * METHOD (method info already done with the generic method code)
1969 table = &assembly->tables [MONO_TABLE_EVENT];
1970 eb->table_idx = table->next_idx ++;
1971 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1972 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1973 values [MONO_EVENT_FLAGS] = eb->attrs;
1974 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1977 * FIXME: we still don't handle 'other' methods
1979 if (eb->add_method) num_methods ++;
1980 if (eb->remove_method) num_methods ++;
1981 if (eb->raise_method) num_methods ++;
1983 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1984 table->rows += num_methods;
1985 alloc_table (table, table->rows);
1987 if (eb->add_method) {
1988 semaidx = table->next_idx ++;
1989 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1990 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1991 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1992 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1994 if (eb->remove_method) {
1995 semaidx = table->next_idx ++;
1996 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1997 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1998 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1999 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2001 if (eb->raise_method) {
2002 semaidx = table->next_idx ++;
2003 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2004 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2005 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2006 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2011 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2013 MonoDynamicTable *table;
2014 guint32 num_constraints, i;
2018 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2019 num_constraints = gparam->iface_constraints ?
2020 mono_array_length (gparam->iface_constraints) : 0;
2021 table->rows += num_constraints;
2022 if (gparam->base_type)
2024 alloc_table (table, table->rows);
2026 if (gparam->base_type) {
2027 table_idx = table->next_idx ++;
2028 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2030 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2031 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2032 assembly, gparam->base_type->type);
2035 for (i = 0; i < num_constraints; i++) {
2036 MonoReflectionType *constraint = mono_array_get (
2037 gparam->iface_constraints, gpointer, i);
2039 table_idx = table->next_idx ++;
2040 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2042 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2043 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2044 assembly, constraint->type);
2049 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2051 GenericParamTableEntry *entry;
2054 * The GenericParam table must be sorted according to the `owner' field.
2055 * We need to do this sorting prior to writing the GenericParamConstraint
2056 * table, since we have to use the final GenericParam table indices there
2057 * and they must also be sorted.
2060 entry = g_new0 (GenericParamTableEntry, 1);
2061 entry->owner = owner;
2063 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2064 MONO_GC_REGISTER_ROOT (entry->gparam);
2066 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2068 g_ptr_array_add (assembly->gen_params, entry);
2072 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2074 MonoDynamicTable *table;
2075 MonoGenericParam *param;
2079 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2080 table_idx = table->next_idx ++;
2081 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2083 param = entry->gparam->type.type->data.generic_param;
2085 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2086 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2087 values [MONO_GENERICPARAM_NUMBER] = param->num;
2088 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2090 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2092 encode_constraints (entry->gparam, table_idx, assembly);
2096 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2098 MonoDynamicTable *table;
2101 guint32 cols [MONO_ASSEMBLY_SIZE];
2105 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2108 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2109 table = &assembly->tables [MONO_TABLE_MODULEREF];
2110 token = table->next_idx ++;
2112 alloc_table (table, table->rows);
2113 values = table->values + token * MONO_MODULEREF_SIZE;
2114 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2116 token <<= MONO_RESOLTION_SCOPE_BITS;
2117 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2118 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2123 if (image->assembly->dynamic)
2125 memset (cols, 0, sizeof (cols));
2127 /* image->assembly->image is the manifest module */
2128 image = image->assembly->image;
2129 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2132 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2133 token = table->next_idx ++;
2135 alloc_table (table, table->rows);
2136 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2137 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2138 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2139 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2140 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2141 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2142 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2143 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2144 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2146 if (strcmp ("", image->assembly->aname.culture)) {
2147 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2148 image->assembly->aname.culture);
2151 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2152 guchar pubtoken [9];
2154 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2155 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2157 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2159 token <<= MONO_RESOLTION_SCOPE_BITS;
2160 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2161 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2166 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2168 MonoDynamicTable *table;
2173 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2176 sigbuffer_init (&buf, 32);
2177 switch (type->type) {
2178 case MONO_TYPE_FNPTR:
2180 case MONO_TYPE_SZARRAY:
2181 case MONO_TYPE_ARRAY:
2183 case MONO_TYPE_MVAR:
2184 case MONO_TYPE_GENERICINST:
2185 encode_type (assembly, type, &buf);
2187 case MONO_TYPE_CLASS:
2188 case MONO_TYPE_VALUETYPE: {
2189 MonoClass *k = mono_class_from_mono_type (type);
2190 if (!k || !k->generic_container) {
2191 sigbuffer_free (&buf);
2194 encode_type (assembly, type, &buf);
2198 sigbuffer_free (&buf);
2202 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2203 if (assembly->save) {
2204 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2205 alloc_table (table, table->rows + 1);
2206 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2207 values [MONO_TYPESPEC_SIGNATURE] = token;
2209 sigbuffer_free (&buf);
2211 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2212 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2218 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2220 MonoDynamicTable *table;
2222 guint32 token, scope, enclosing;
2225 /* if the type requires a typespec, we must try that first*/
2226 if (try_typespec && (token = create_typespec (assembly, type)))
2228 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2231 klass = my_mono_class_from_mono_type (type);
2233 klass = mono_class_from_mono_type (type);
2236 * If it's in the same module and not a generic type parameter:
2238 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2239 (type->type != MONO_TYPE_MVAR)) {
2240 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2241 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2242 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2246 if (klass->nested_in) {
2247 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2248 /* get the typeref idx of the enclosing type */
2249 enclosing >>= MONO_TYPEDEFORREF_BITS;
2250 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2252 scope = resolution_scope_from_image (assembly, klass->image);
2254 table = &assembly->tables [MONO_TABLE_TYPEREF];
2255 if (assembly->save) {
2256 alloc_table (table, table->rows + 1);
2257 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2258 values [MONO_TYPEREF_SCOPE] = scope;
2259 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2260 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2262 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2263 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2265 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2270 * Despite the name, we handle also TypeSpec (with the above helper).
2273 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2275 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2279 * Insert a memberef row into the metadata: the token that point to the memberref
2280 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2281 * mono_image_get_fieldref_token()).
2282 * The sig param is an index to an already built signature.
2285 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2287 MonoDynamicTable *table;
2289 guint32 token, pclass;
2292 parent = mono_image_typedef_or_ref (assembly, type);
2293 switch (parent & MONO_TYPEDEFORREF_MASK) {
2294 case MONO_TYPEDEFORREF_TYPEREF:
2295 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2297 case MONO_TYPEDEFORREF_TYPESPEC:
2298 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2300 case MONO_TYPEDEFORREF_TYPEDEF:
2301 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2304 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2307 /* extract the index */
2308 parent >>= MONO_TYPEDEFORREF_BITS;
2310 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2312 if (assembly->save) {
2313 alloc_table (table, table->rows + 1);
2314 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2315 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2316 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2317 values [MONO_MEMBERREF_SIGNATURE] = sig;
2320 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2327 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2330 MonoMethodSignature *sig;
2332 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2337 * A methodref signature can't contain an unmanaged calling convention.
2339 sig = mono_metadata_signature_dup (mono_method_signature (method));
2340 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2341 sig->call_convention = MONO_CALL_DEFAULT;
2342 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2343 method->name, method_encode_signature (assembly, sig));
2345 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2350 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2351 const gchar *name, guint32 sig)
2353 MonoDynamicTable *table;
2357 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2359 if (assembly->save) {
2360 alloc_table (table, table->rows + 1);
2361 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2362 values [MONO_MEMBERREF_CLASS] = original;
2363 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2364 values [MONO_MEMBERREF_SIGNATURE] = sig;
2367 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2374 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2377 ReflectionMethodBuilder rmb;
2379 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2383 reflection_methodbuilder_from_method_builder (&rmb, mb);
2385 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2386 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2387 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2392 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2395 ReflectionMethodBuilder rmb;
2397 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2401 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2403 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2404 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2405 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2410 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2415 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2418 g_assert (f->field->parent);
2419 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2420 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2421 f->field->name, fieldref_encode_signature (assembly, type));
2422 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2427 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2431 guint32 nparams = context->method_inst->type_argc;
2434 if (!assembly->save)
2437 sigbuffer_init (&buf, 32);
2439 * FIXME: vararg, explicit_this, differenc call_conv values...
2441 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2442 sigbuffer_add_value (&buf, nparams);
2444 for (i = 0; i < nparams; i++)
2445 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2447 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2448 sigbuffer_free (&buf);
2453 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2455 MonoDynamicTable *table;
2457 guint32 token, mtoken = 0, sig;
2458 MonoMethodInflated *imethod;
2459 MonoMethod *declaring;
2461 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2463 g_assert (method->is_inflated);
2464 imethod = (MonoMethodInflated *) method;
2465 declaring = imethod->declaring;
2467 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2468 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2470 if (!mono_method_signature (declaring)->generic_param_count)
2473 switch (mono_metadata_token_table (mtoken)) {
2474 case MONO_TABLE_MEMBERREF:
2475 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2477 case MONO_TABLE_METHOD:
2478 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2481 g_assert_not_reached ();
2484 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2486 if (assembly->save) {
2487 alloc_table (table, table->rows + 1);
2488 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2489 values [MONO_METHODSPEC_METHOD] = mtoken;
2490 values [MONO_METHODSPEC_SIGNATURE] = sig;
2493 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2500 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2502 MonoMethodInflated *imethod;
2505 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2509 g_assert (method->is_inflated);
2510 imethod = (MonoMethodInflated *) method;
2512 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2513 token = method_encode_methodspec (assembly, method);
2515 guint32 sig = method_encode_signature (
2516 assembly, mono_method_signature (imethod->declaring));
2517 token = mono_image_get_memberref_token (
2518 assembly, &method->klass->byval_arg, method->name, sig);
2521 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2526 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2528 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2531 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2532 token = mono_image_get_memberref_token (
2533 assembly, &m->klass->byval_arg, m->name, sig);
2539 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2541 MonoDynamicTable *table;
2549 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2550 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2551 * Because of this, we must not insert it into the `typeref' hash table.
2554 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2558 sigbuffer_init (&buf, 32);
2560 g_assert (tb->generic_params);
2561 klass = mono_class_from_mono_type (tb->type.type);
2563 if (tb->generic_container)
2564 mono_reflection_create_generic_class (tb);
2566 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2567 g_assert (klass->generic_container);
2568 sigbuffer_add_value (&buf, klass->byval_arg.type);
2569 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2571 count = mono_array_length (tb->generic_params);
2572 sigbuffer_add_value (&buf, count);
2573 for (i = 0; i < count; i++) {
2574 MonoReflectionGenericParam *gparam;
2576 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2578 encode_type (assembly, gparam->type.type, &buf);
2581 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2583 if (assembly->save) {
2584 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2585 alloc_table (table, table->rows + 1);
2586 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2587 values [MONO_TYPESPEC_SIGNATURE] = token;
2589 sigbuffer_free (&buf);
2591 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2592 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2598 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2600 MonoDynamicTable *table;
2603 guint32 token, pclass, parent, sig;
2606 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2610 klass = mono_class_from_mono_type (fb->typeb->type);
2611 name = mono_string_to_utf8 (fb->name);
2613 sig = fieldref_encode_signature (assembly, fb->type->type);
2615 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2616 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2618 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2619 parent >>= MONO_TYPEDEFORREF_BITS;
2621 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2623 if (assembly->save) {
2624 alloc_table (table, table->rows + 1);
2625 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2626 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2627 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2628 values [MONO_MEMBERREF_SIGNATURE] = sig;
2631 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2633 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2638 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2645 if (!assembly->save)
2648 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2649 g_assert (helper->type == 2);
2651 if (helper->arguments)
2652 nargs = mono_array_length (helper->arguments);
2656 size = 10 + (nargs * 10);
2658 sigbuffer_init (&buf, 32);
2660 /* Encode calling convention */
2661 /* Change Any to Standard */
2662 if ((helper->call_conv & 0x03) == 0x03)
2663 helper->call_conv = 0x01;
2664 /* explicit_this implies has_this */
2665 if (helper->call_conv & 0x40)
2666 helper->call_conv &= 0x20;
2668 if (helper->call_conv == 0) { /* Unmanaged */
2669 idx = helper->unmanaged_call_conv - 1;
2672 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2673 if (helper->call_conv & 0x02) /* varargs */
2677 sigbuffer_add_byte (&buf, idx);
2678 sigbuffer_add_value (&buf, nargs);
2679 encode_reflection_type (assembly, helper->return_type, &buf);
2680 for (i = 0; i < nargs; ++i) {
2681 MonoArray *modreqs = NULL;
2682 MonoArray *modopts = NULL;
2683 MonoReflectionType *pt;
2685 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
2686 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
2687 if (helper->modopts && (i < mono_array_length (helper->modopts)))
2688 modopts = mono_array_get (helper->modopts, MonoArray*, i);
2690 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
2691 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2692 encode_reflection_type (assembly, pt, &buf);
2694 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2695 sigbuffer_free (&buf);
2701 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2704 MonoDynamicTable *table;
2707 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2708 idx = table->next_idx ++;
2710 alloc_table (table, table->rows);
2711 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2713 values [MONO_STAND_ALONE_SIGNATURE] =
2714 mono_reflection_encode_sighelper (assembly, helper);
2720 reflection_cc_to_file (int call_conv) {
2721 switch (call_conv & 0x3) {
2723 case 1: return MONO_CALL_DEFAULT;
2724 case 2: return MONO_CALL_VARARG;
2726 g_assert_not_reached ();
2733 MonoMethodSignature *sig;
2739 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2744 MonoMethodSignature *sig;
2747 name = mono_string_to_utf8 (m->name);
2748 nparams = mono_array_length (m->parameters);
2749 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2751 sig->sentinelpos = -1;
2752 sig->call_convention = reflection_cc_to_file (m->call_conv);
2753 sig->param_count = nparams;
2754 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2755 for (i = 0; i < nparams; ++i) {
2756 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2757 sig->params [i] = t->type;
2760 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2762 if (strcmp (name, am->name) == 0 &&
2763 mono_metadata_type_equal (am->parent, m->parent->type) &&
2764 mono_metadata_signature_equal (am->sig, sig)) {
2767 m->table_idx = am->token & 0xffffff;
2771 am = g_new0 (ArrayMethod, 1);
2774 am->parent = m->parent->type;
2775 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2776 method_encode_signature (assembly, sig));
2777 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2778 m->table_idx = am->token & 0xffffff;
2783 * Insert into the metadata tables all the info about the TypeBuilder tb.
2784 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2787 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2789 MonoDynamicTable *table;
2791 int i, is_object = 0, is_system = 0;
2794 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2795 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2796 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2797 n = mono_string_to_utf8 (tb->name);
2798 if (strcmp (n, "Object") == 0)
2800 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2802 n = mono_string_to_utf8 (tb->nspace);
2803 if (strcmp (n, "System") == 0)
2805 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2807 if (tb->parent && !(is_system && is_object) &&
2808 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2809 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2811 values [MONO_TYPEDEF_EXTENDS] = 0;
2813 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2814 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2817 * if we have explicitlayout or sequentiallayouts, output data in the
2818 * ClassLayout table.
2820 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2821 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2822 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2824 alloc_table (table, table->rows);
2825 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2826 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2827 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2828 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2831 /* handle interfaces */
2832 if (tb->interfaces) {
2833 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2835 table->rows += mono_array_length (tb->interfaces);
2836 alloc_table (table, table->rows);
2837 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2838 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2839 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2840 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2841 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2842 values += MONO_INTERFACEIMPL_SIZE;
2848 table = &assembly->tables [MONO_TABLE_FIELD];
2849 table->rows += tb->num_fields;
2850 alloc_table (table, table->rows);
2851 for (i = 0; i < tb->num_fields; ++i)
2852 mono_image_get_field_info (
2853 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2856 /* handle constructors */
2858 table = &assembly->tables [MONO_TABLE_METHOD];
2859 table->rows += mono_array_length (tb->ctors);
2860 alloc_table (table, table->rows);
2861 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2862 mono_image_get_ctor_info (domain,
2863 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2866 /* handle methods */
2868 table = &assembly->tables [MONO_TABLE_METHOD];
2869 table->rows += tb->num_methods;
2870 alloc_table (table, table->rows);
2871 for (i = 0; i < tb->num_methods; ++i)
2872 mono_image_get_method_info (
2873 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2876 /* Do the same with properties etc.. */
2877 if (tb->events && mono_array_length (tb->events)) {
2878 table = &assembly->tables [MONO_TABLE_EVENT];
2879 table->rows += mono_array_length (tb->events);
2880 alloc_table (table, table->rows);
2881 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2883 alloc_table (table, table->rows);
2884 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2885 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2886 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2887 for (i = 0; i < mono_array_length (tb->events); ++i)
2888 mono_image_get_event_info (
2889 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2891 if (tb->properties && mono_array_length (tb->properties)) {
2892 table = &assembly->tables [MONO_TABLE_PROPERTY];
2893 table->rows += mono_array_length (tb->properties);
2894 alloc_table (table, table->rows);
2895 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2897 alloc_table (table, table->rows);
2898 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2899 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2900 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2901 for (i = 0; i < mono_array_length (tb->properties); ++i)
2902 mono_image_get_property_info (
2903 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2906 /* handle generic parameters */
2907 if (tb->generic_params) {
2908 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2909 table->rows += mono_array_length (tb->generic_params);
2910 alloc_table (table, table->rows);
2911 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2912 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2914 mono_image_get_generic_param_info (
2915 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2919 mono_image_add_decl_security (assembly,
2920 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2923 MonoDynamicTable *ntable;
2925 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2926 ntable->rows += mono_array_length (tb->subtypes);
2927 alloc_table (ntable, ntable->rows);
2928 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2930 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2931 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2933 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2934 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2935 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2936 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2937 mono_string_to_utf8 (tb->name), tb->table_idx,
2938 ntable->next_idx, ntable->rows);*/
2939 values += MONO_NESTED_CLASS_SIZE;
2946 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2950 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2952 if (!type->subtypes)
2955 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2956 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2957 collect_types (types, subtype);
2962 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2964 if ((*type1)->table_idx < (*type2)->table_idx)
2967 if ((*type1)->table_idx > (*type2)->table_idx)
2974 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2979 for (i = 0; i < mono_array_length (pinfo); ++i) {
2980 MonoReflectionParamBuilder *pb;
2981 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2984 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2989 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2992 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2994 for (i = 0; i < tb->num_fields; ++i) {
2995 MonoReflectionFieldBuilder* fb;
2996 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2997 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3001 for (i = 0; i < mono_array_length (tb->events); ++i) {
3002 MonoReflectionEventBuilder* eb;
3003 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3004 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3007 if (tb->properties) {
3008 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3009 MonoReflectionPropertyBuilder* pb;
3010 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3011 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3015 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3016 MonoReflectionCtorBuilder* cb;
3017 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3018 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3019 params_add_cattrs (assembly, cb->pinfo);
3024 for (i = 0; i < tb->num_methods; ++i) {
3025 MonoReflectionMethodBuilder* mb;
3026 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3027 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3028 params_add_cattrs (assembly, mb->pinfo);
3033 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3034 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3039 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3043 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3045 if (moduleb->global_methods) {
3046 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3047 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3048 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3049 params_add_cattrs (assembly, mb->pinfo);
3053 if (moduleb->global_fields) {
3054 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3055 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3056 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3060 if (moduleb->types) {
3061 for (i = 0; i < moduleb->num_types; ++i)
3062 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3067 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3069 MonoDynamicTable *table;
3073 char *b = blob_size;
3076 table = &assembly->tables [MONO_TABLE_FILE];
3078 alloc_table (table, table->rows);
3079 values = table->values + table->next_idx * MONO_FILE_SIZE;
3080 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3081 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3082 if (module->image->dynamic) {
3083 /* This depends on the fact that the main module is emitted last */
3084 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3085 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3088 path = g_strdup (module->image->name);
3090 mono_sha1_get_digest_from_file (path, hash);
3093 mono_metadata_encode_value (20, b, &b);
3094 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3095 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3100 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3102 MonoDynamicTable *table;
3105 table = &assembly->tables [MONO_TABLE_MODULE];
3106 mb->table_idx = table->next_idx ++;
3107 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3108 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3111 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3112 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3113 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3114 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3118 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3119 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3121 MonoDynamicTable *table;
3125 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3126 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3129 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3131 alloc_table (table, table->rows);
3132 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3134 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3135 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3136 if (klass->nested_in)
3137 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3139 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3140 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3141 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3143 res = table->next_idx;
3147 /* Emit nested types */
3148 if (klass->nested_classes) {
3151 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3152 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3159 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3160 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3165 klass = mono_class_from_mono_type (tb->type.type);
3167 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3169 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3170 parent_index, assembly);
3174 * We need to do this ourselves since klass->nested_classes is not set up.
3177 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3178 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3183 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3184 guint32 module_index, MonoDynamicImage *assembly)
3186 MonoImage *image = module->image;
3190 t = &image->tables [MONO_TABLE_TYPEDEF];
3192 for (i = 0; i < t->rows; ++i) {
3193 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3195 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3196 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3201 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3203 MonoDynamicTable *table;
3209 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3211 if (assemblyb->type_forwarders) {
3212 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3213 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3219 klass = mono_class_from_mono_type (t->type);
3221 scope = resolution_scope_from_image (assembly, klass->image);
3222 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3223 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3226 alloc_table (table, table->rows);
3227 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3229 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3230 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3231 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3232 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3233 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3238 #define align_pointer(base,p)\
3240 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3242 (p) += 4 - (__diff & 3);\
3246 compare_constants (const void *a, const void *b)
3248 const guint32 *a_values = a;
3249 const guint32 *b_values = b;
3250 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3254 compare_semantics (const void *a, const void *b)
3256 const guint32 *a_values = a;
3257 const guint32 *b_values = b;
3258 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3261 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3265 compare_custom_attrs (const void *a, const void *b)
3267 const guint32 *a_values = a;
3268 const guint32 *b_values = b;
3270 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3274 compare_field_marshal (const void *a, const void *b)
3276 const guint32 *a_values = a;
3277 const guint32 *b_values = b;
3279 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3283 compare_nested (const void *a, const void *b)
3285 const guint32 *a_values = a;
3286 const guint32 *b_values = b;
3288 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3292 compare_genericparam (const void *a, const void *b)
3294 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3295 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3297 if ((*b_entry)->owner == (*a_entry)->owner)
3299 (*a_entry)->gparam->type.type->data.generic_param->num -
3300 (*b_entry)->gparam->type.type->data.generic_param->num;
3302 return (*a_entry)->owner - (*b_entry)->owner;
3306 compare_declsecurity_attrs (const void *a, const void *b)
3308 const guint32 *a_values = a;
3309 const guint32 *b_values = b;
3311 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3315 pad_heap (MonoDynamicStream *sh)
3317 if (sh->index & 3) {
3318 int sz = 4 - (sh->index & 3);
3319 memset (sh->data + sh->index, 0, sz);
3326 MonoDynamicStream *stream;
3330 * build_compressed_metadata() fills in the blob of data that represents the
3331 * raw metadata as it will be saved in the PE file. The five streams are output
3332 * and the metadata tables are comnpressed from the guint32 array representation,
3333 * to the compressed on-disk format.
3336 build_compressed_metadata (MonoDynamicImage *assembly)
3338 MonoDynamicTable *table;
3340 guint64 valid_mask = 0;
3341 guint64 sorted_mask;
3342 guint32 heapt_size = 0;
3343 guint32 meta_size = 256; /* allow for header and other stuff */
3344 guint32 table_offset;
3345 guint32 ntables = 0;
3351 struct StreamDesc stream_desc [5];
3353 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3354 for (i = 0; i < assembly->gen_params->len; i++){
3355 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3356 write_generic_param_entry (assembly, entry);
3359 stream_desc [0].name = "#~";
3360 stream_desc [0].stream = &assembly->tstream;
3361 stream_desc [1].name = "#Strings";
3362 stream_desc [1].stream = &assembly->sheap;
3363 stream_desc [2].name = "#US";
3364 stream_desc [2].stream = &assembly->us;
3365 stream_desc [3].name = "#Blob";
3366 stream_desc [3].stream = &assembly->blob;
3367 stream_desc [4].name = "#GUID";
3368 stream_desc [4].stream = &assembly->guid;
3370 /* tables that are sorted */
3371 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3372 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3373 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3374 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3375 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3376 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3378 /* Compute table sizes */
3379 /* the MonoImage has already been created in mono_image_basic_init() */
3380 meta = &assembly->image;
3382 /* sizes should be multiple of 4 */
3383 pad_heap (&assembly->blob);
3384 pad_heap (&assembly->guid);
3385 pad_heap (&assembly->sheap);
3386 pad_heap (&assembly->us);
3388 /* Setup the info used by compute_sizes () */
3389 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3390 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3391 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3393 meta_size += assembly->blob.index;
3394 meta_size += assembly->guid.index;
3395 meta_size += assembly->sheap.index;
3396 meta_size += assembly->us.index;
3398 for (i=0; i < MONO_TABLE_NUM; ++i)
3399 meta->tables [i].rows = assembly->tables [i].rows;
3401 for (i = 0; i < MONO_TABLE_NUM; i++){
3402 if (meta->tables [i].rows == 0)
3404 valid_mask |= (guint64)1 << i;
3406 meta->tables [i].row_size = mono_metadata_compute_size (
3407 meta, i, &meta->tables [i].size_bitfield);
3408 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3410 heapt_size += 24; /* #~ header size */
3411 heapt_size += ntables * 4;
3412 /* make multiple of 4 */
3415 meta_size += heapt_size;
3416 meta->raw_metadata = g_malloc0 (meta_size);
3417 p = (unsigned char*)meta->raw_metadata;
3418 /* the metadata signature */
3419 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3420 /* version numbers and 4 bytes reserved */
3421 int16val = (guint16*)p;
3422 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3423 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3425 /* version string */
3426 int32val = (guint32*)p;
3427 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3429 memcpy (p, meta->version, strlen (meta->version));
3430 p += GUINT32_FROM_LE (*int32val);
3431 align_pointer (meta->raw_metadata, p);
3432 int16val = (guint16*)p;
3433 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3434 *int16val = GUINT16_TO_LE (5); /* number of streams */
3438 * write the stream info.
3440 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3441 table_offset += 3; table_offset &= ~3;
3443 assembly->tstream.index = heapt_size;
3444 for (i = 0; i < 5; ++i) {
3445 int32val = (guint32*)p;
3446 stream_desc [i].stream->offset = table_offset;
3447 *int32val++ = GUINT32_TO_LE (table_offset);
3448 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3449 table_offset += GUINT32_FROM_LE (*int32val);
3450 table_offset += 3; table_offset &= ~3;
3452 strcpy ((char*)p, stream_desc [i].name);
3453 p += strlen (stream_desc [i].name) + 1;
3454 align_pointer (meta->raw_metadata, p);
3457 * now copy the data, the table stream header and contents goes first.
3459 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3460 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3461 int32val = (guint32*)p;
3462 *int32val = GUINT32_TO_LE (0); /* reserved */
3465 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3466 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3467 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3468 *p++ = 2; /* version */
3471 *p++ = 1; /* version */
3475 if (meta->idx_string_wide)
3477 if (meta->idx_guid_wide)
3479 if (meta->idx_blob_wide)
3482 *p++ = 1; /* reserved */
3483 int64val = (guint64*)p;
3484 *int64val++ = GUINT64_TO_LE (valid_mask);
3485 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3487 int32val = (guint32*)p;
3488 for (i = 0; i < MONO_TABLE_NUM; i++){
3489 if (meta->tables [i].rows == 0)
3491 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3493 p = (unsigned char*)int32val;
3495 /* sort the tables that still need sorting */
3496 table = &assembly->tables [MONO_TABLE_CONSTANT];
3498 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3499 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3501 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3502 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3504 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3505 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3507 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3508 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3510 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3511 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3512 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3514 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3516 /* compress the tables */
3517 for (i = 0; i < MONO_TABLE_NUM; i++){
3520 guint32 bitfield = meta->tables [i].size_bitfield;
3521 if (!meta->tables [i].rows)
3523 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3524 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3525 meta->tables [i].base = (char*)p;
3526 for (row = 1; row <= meta->tables [i].rows; ++row) {
3527 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3528 for (col = 0; col < assembly->tables [i].columns; ++col) {
3529 switch (mono_metadata_table_size (bitfield, col)) {
3531 *p++ = values [col];
3534 *p++ = values [col] & 0xff;
3535 *p++ = (values [col] >> 8) & 0xff;
3538 *p++ = values [col] & 0xff;
3539 *p++ = (values [col] >> 8) & 0xff;
3540 *p++ = (values [col] >> 16) & 0xff;
3541 *p++ = (values [col] >> 24) & 0xff;
3544 g_assert_not_reached ();
3548 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3551 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3552 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3553 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3554 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3555 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3557 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3561 * Some tables in metadata need to be sorted according to some criteria, but
3562 * when methods and fields are first created with reflection, they may be assigned a token
3563 * that doesn't correspond to the final token they will get assigned after the sorting.
3564 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3565 * with the reflection objects that represent them. Once all the tables are set up, the
3566 * reflection objects will contains the correct table index. fixup_method() will fixup the
3567 * tokens for the method with ILGenerator @ilgen.
3570 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3571 guint32 code_idx = GPOINTER_TO_UINT (value);
3572 MonoReflectionILTokenInfo *iltoken;
3573 MonoReflectionFieldBuilder *field;
3574 MonoReflectionCtorBuilder *ctor;
3575 MonoReflectionMethodBuilder *method;
3576 MonoReflectionTypeBuilder *tb;
3577 MonoReflectionArrayMethod *am;
3579 unsigned char *target;
3581 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3582 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3583 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3584 switch (target [3]) {
3585 case MONO_TABLE_FIELD:
3586 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3587 field = (MonoReflectionFieldBuilder *)iltoken->member;
3588 idx = field->table_idx;
3589 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3590 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3591 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3593 g_assert_not_reached ();
3596 case MONO_TABLE_METHOD:
3597 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3598 method = (MonoReflectionMethodBuilder *)iltoken->member;
3599 idx = method->table_idx;
3600 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3601 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3602 idx = ctor->table_idx;
3603 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3604 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3605 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3606 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3608 g_assert_not_reached ();
3611 case MONO_TABLE_TYPEDEF:
3612 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3613 g_assert_not_reached ();
3614 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3615 idx = tb->table_idx;
3617 case MONO_TABLE_MEMBERREF:
3618 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3619 am = (MonoReflectionArrayMethod*)iltoken->member;
3620 idx = am->table_idx;
3621 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3622 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3623 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3624 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3625 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3626 g_assert (m->klass->generic_class || m->klass->generic_container);
3628 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3630 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3631 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3632 g_assert (f->generic_info);
3634 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3635 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3638 g_assert_not_reached ();
3641 case MONO_TABLE_METHODSPEC:
3642 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3643 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3644 g_assert (mono_method_signature (m)->generic_param_count);
3647 g_assert_not_reached ();
3651 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3653 target [0] = idx & 0xff;
3654 target [1] = (idx >> 8) & 0xff;
3655 target [2] = (idx >> 16) & 0xff;
3662 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3663 * value is not known when the table is emitted.
3666 fixup_cattrs (MonoDynamicImage *assembly)
3668 MonoDynamicTable *table;
3670 guint32 type, i, idx, token;
3673 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3675 for (i = 0; i < table->rows; ++i) {
3676 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3678 type = values [MONO_CUSTOM_ATTR_TYPE];
3679 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3680 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3681 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3682 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3685 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3686 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3687 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3688 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3695 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3697 MonoDynamicTable *table;
3700 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3702 alloc_table (table, table->rows);
3703 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3704 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3705 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3706 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3707 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3712 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3714 MonoDynamicTable *table;
3718 char *b = blob_size;
3720 guint32 idx, offset;
3722 if (rsrc->filename) {
3723 name = mono_string_to_utf8 (rsrc->filename);
3724 sname = g_path_get_basename (name);
3726 table = &assembly->tables [MONO_TABLE_FILE];
3728 alloc_table (table, table->rows);
3729 values = table->values + table->next_idx * MONO_FILE_SIZE;
3730 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3731 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3734 mono_sha1_get_digest_from_file (name, hash);
3735 mono_metadata_encode_value (20, b, &b);
3736 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3737 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3739 idx = table->next_idx++;
3741 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3747 data = mono_array_addr (rsrc->data, char, 0);
3748 len = mono_array_length (rsrc->data);
3754 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3755 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3756 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3757 mono_image_add_stream_data (&assembly->resources, data, len);
3761 * The entry should be emitted into the MANIFESTRESOURCE table of
3762 * the main module, but that needs to reference the FILE table
3763 * which isn't emitted yet.
3770 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3774 set_version_from_string (MonoString *version, guint32 *values)
3776 gchar *ver, *p, *str;
3779 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3780 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3781 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3782 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3785 ver = str = mono_string_to_utf8 (version);
3786 for (i = 0; i < 4; ++i) {
3787 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3793 /* handle Revision and Build */
3803 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3807 char *b = blob_size;
3812 len = mono_array_length (pkey);
3813 mono_metadata_encode_value (len, b, &b);
3814 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3815 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
3817 assembly->public_key = g_malloc (len);
3818 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
3819 assembly->public_key_len = len;
3821 /* Special case: check for ECMA key (16 bytes) */
3822 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
3823 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3824 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3825 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3826 /* minimum key size (in 2.0) is 384 bits */
3827 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3829 /* FIXME - verifier */
3830 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3831 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3833 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3839 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3841 MonoDynamicTable *table;
3842 MonoDynamicImage *assembly;
3843 MonoReflectionAssemblyBuilder *assemblyb;
3847 guint32 module_index;
3849 assemblyb = moduleb->assemblyb;
3850 assembly = moduleb->dynamic_image;
3851 domain = mono_object_domain (assemblyb);
3853 /* Emit ASSEMBLY table */
3854 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3855 alloc_table (table, 1);
3856 values = table->values + MONO_ASSEMBLY_SIZE;
3857 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3858 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3859 if (assemblyb->culture) {
3860 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3862 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3864 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3865 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3866 set_version_from_string (assemblyb->version, values);
3868 /* Emit FILE + EXPORTED_TYPE table */
3870 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3872 MonoReflectionModuleBuilder *file_module =
3873 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3874 if (file_module != moduleb) {
3875 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3877 if (file_module->types) {
3878 for (j = 0; j < file_module->num_types; ++j) {
3879 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3880 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3885 if (assemblyb->loaded_modules) {
3886 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3887 MonoReflectionModule *file_module =
3888 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3889 mono_image_fill_file_table (domain, file_module, assembly);
3891 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3894 if (assemblyb->type_forwarders)
3895 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3897 /* Emit MANIFESTRESOURCE table */
3899 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3901 MonoReflectionModuleBuilder *file_module =
3902 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3903 /* The table for the main module is emitted later */
3904 if (file_module != moduleb) {
3906 if (file_module->resources) {
3907 int len = mono_array_length (file_module->resources);
3908 for (j = 0; j < len; ++j) {
3909 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3910 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3918 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3919 * for the modulebuilder @moduleb.
3920 * At the end of the process, method and field tokens are fixed up and the
3921 * on-disk compressed metadata representation is created.
3924 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3926 MonoDynamicTable *table;
3927 MonoDynamicImage *assembly;
3928 MonoReflectionAssemblyBuilder *assemblyb;
3934 assemblyb = moduleb->assemblyb;
3935 assembly = moduleb->dynamic_image;
3936 domain = mono_object_domain (assemblyb);
3938 if (assembly->text_rva)
3941 assembly->text_rva = START_TEXT_RVA;
3943 if (moduleb->is_main) {
3944 mono_image_emit_manifest (moduleb);
3947 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3948 table->rows = 1; /* .<Module> */
3950 alloc_table (table, table->rows);
3952 * Set the first entry.
3954 values = table->values + table->columns;
3955 values [MONO_TYPEDEF_FLAGS] = 0;
3956 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3957 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3958 values [MONO_TYPEDEF_EXTENDS] = 0;
3959 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3960 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3963 * handle global methods
3964 * FIXME: test what to do when global methods are defined in multiple modules.
3966 if (moduleb->global_methods) {
3967 table = &assembly->tables [MONO_TABLE_METHOD];
3968 table->rows += mono_array_length (moduleb->global_methods);
3969 alloc_table (table, table->rows);
3970 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3971 mono_image_get_method_info (
3972 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3974 if (moduleb->global_fields) {
3975 table = &assembly->tables [MONO_TABLE_FIELD];
3976 table->rows += mono_array_length (moduleb->global_fields);
3977 alloc_table (table, table->rows);
3978 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3979 mono_image_get_field_info (
3980 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3983 table = &assembly->tables [MONO_TABLE_MODULE];
3984 alloc_table (table, 1);
3985 mono_image_fill_module_table (domain, moduleb, assembly);
3987 /* Collect all types into a list sorted by their table_idx */
3988 types = g_ptr_array_new ();
3991 for (i = 0; i < moduleb->num_types; ++i) {
3992 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3993 collect_types (types, type);
3996 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3997 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3998 table->rows += types->len;
3999 alloc_table (table, table->rows);
4002 * Emit type names + namespaces at one place inside the string heap,
4003 * so load_class_names () needs to touch fewer pages.
4005 for (i = 0; i < types->len; ++i) {
4006 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4007 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4009 for (i = 0; i < types->len; ++i) {
4010 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4011 string_heap_insert_mstring (&assembly->sheap, tb->name);
4014 for (i = 0; i < types->len; ++i) {
4015 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4016 mono_image_get_type_info (domain, type, assembly);
4020 * table->rows is already set above and in mono_image_fill_module_table.
4022 /* add all the custom attributes at the end, once all the indexes are stable */
4023 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4025 /* CAS assembly permissions */
4026 if (assemblyb->permissions_minimum)
4027 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4028 if (assemblyb->permissions_optional)
4029 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4030 if (assemblyb->permissions_refused)
4031 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4033 module_add_cattrs (assembly, moduleb);
4036 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4038 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4039 * the final tokens and don't need another fixup pass. */
4041 if (moduleb->global_methods) {
4042 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4043 MonoReflectionMethodBuilder *mb = mono_array_get (
4044 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4045 mono_image_add_methodimpl (assembly, mb);
4049 for (i = 0; i < types->len; ++i) {
4050 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4051 if (type->methods) {
4052 for (j = 0; j < type->num_methods; ++j) {
4053 MonoReflectionMethodBuilder *mb = mono_array_get (
4054 type->methods, MonoReflectionMethodBuilder*, j);
4056 mono_image_add_methodimpl (assembly, mb);
4061 g_ptr_array_free (types, TRUE);
4063 fixup_cattrs (assembly);
4067 * mono_image_insert_string:
4068 * @module: module builder object
4071 * Insert @str into the user string stream of @module.
4074 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4076 MonoDynamicImage *assembly;
4081 MONO_ARCH_SAVE_REGS;
4083 if (!module->dynamic_image)
4084 mono_image_module_basic_init (module);
4086 assembly = module->dynamic_image;
4088 if (assembly->save) {
4089 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4090 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4091 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4093 char *swapped = g_malloc (2 * mono_string_length (str));
4094 const char *p = (const char*)mono_string_chars (str);
4096 swap_with_size (swapped, p, 2, mono_string_length (str));
4097 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4101 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4103 mono_image_add_stream_data (&assembly->us, "", 1);
4105 idx = assembly->us.index ++;
4108 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4110 return MONO_TOKEN_STRING | idx;
4114 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4119 klass = obj->vtable->klass;
4120 if (strcmp (klass->name, "MonoMethod") == 0) {
4121 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4122 MonoMethodSignature *sig, *old;
4123 guint32 sig_token, parent;
4126 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4128 nargs = mono_array_length (opt_param_types);
4129 old = mono_method_signature (method);
4130 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4132 sig->hasthis = old->hasthis;
4133 sig->explicit_this = old->explicit_this;
4134 sig->call_convention = old->call_convention;
4135 sig->generic_param_count = old->generic_param_count;
4136 sig->param_count = old->param_count + nargs;
4137 sig->sentinelpos = old->param_count;
4138 sig->ret = old->ret;
4140 for (i = 0; i < old->param_count; i++)
4141 sig->params [i] = old->params [i];
4143 for (i = 0; i < nargs; i++) {
4144 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4145 sig->params [old->param_count + i] = rt->type;
4148 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4149 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4150 parent >>= MONO_TYPEDEFORREF_BITS;
4152 parent <<= MONO_MEMBERREF_PARENT_BITS;
4153 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4155 sig_token = method_encode_signature (assembly, sig);
4156 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4157 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4158 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4159 ReflectionMethodBuilder rmb;
4160 guint32 parent, sig;
4162 reflection_methodbuilder_from_method_builder (&rmb, mb);
4163 rmb.opt_types = opt_param_types;
4165 sig = method_builder_encode_signature (assembly, &rmb);
4167 parent = mono_image_create_token (assembly, obj, TRUE);
4168 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4170 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4171 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4173 token = mono_image_get_varargs_method_token (
4174 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4176 g_error ("requested method token for %s\n", klass->name);
4183 * mono_image_create_token:
4184 * @assembly: a dynamic assembly
4187 * Get a token to insert in the IL code stream for the given MemberInfo.
4188 * @obj can be one of:
4189 * ConstructorBuilder
4192 * GenericTypeParameterBuilder
4200 * MonoGenericCMethod
4206 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4211 klass = obj->vtable->klass;
4212 if (strcmp (klass->name, "MethodBuilder") == 0) {
4213 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4214 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4216 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4217 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4219 token = mono_image_get_methodbuilder_token (assembly, mb);
4220 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4221 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4222 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4223 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4225 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4226 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4228 token = mono_image_get_ctorbuilder_token (assembly, mb);
4229 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4230 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4231 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4232 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4233 if (tb->generic_params) {
4234 token = mono_image_get_generic_field_token (assembly, fb);
4236 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4238 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4239 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4240 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4241 } else if (strcmp (klass->name, "MonoType") == 0) {
4242 MonoReflectionType *tb = (MonoReflectionType *)obj;
4243 MonoClass *mc = mono_class_from_mono_type (tb->type);
4244 token = mono_metadata_token_from_dor (
4245 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4246 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4247 MonoReflectionType *tb = (MonoReflectionType *)obj;
4248 token = mono_metadata_token_from_dor (
4249 mono_image_typedef_or_ref (assembly, tb->type));
4250 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4251 MonoReflectionType *tb = (MonoReflectionType *)obj;
4252 token = mono_metadata_token_from_dor (
4253 mono_image_typedef_or_ref (assembly, tb->type));
4254 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4255 strcmp (klass->name, "MonoMethod") == 0 ||
4256 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4257 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4258 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4259 if (m->method->is_inflated) {
4260 if (create_methodspec)
4261 token = mono_image_get_methodspec_token (assembly, m->method);
4263 token = mono_image_get_inflated_method_token (assembly, m->method);
4264 } else if ((m->method->klass->image == &assembly->image) &&
4265 !m->method->klass->generic_class) {
4266 static guint32 method_table_idx = 0xffffff;
4267 if (m->method->klass->wastypebuilder) {
4268 /* we use the same token as the one that was assigned
4269 * to the Methodbuilder.
4270 * FIXME: do the equivalent for Fields.
4272 token = m->method->token;
4275 * Each token should have a unique index, but the indexes are
4276 * assigned by managed code, so we don't know about them. An
4277 * easy solution is to count backwards...
4279 method_table_idx --;
4280 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4283 token = mono_image_get_methodref_token (assembly, m->method);
4285 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4286 } else if (strcmp (klass->name, "MonoField") == 0) {
4287 MonoReflectionField *f = (MonoReflectionField *)obj;
4288 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4289 static guint32 field_table_idx = 0xffffff;
4291 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4293 token = mono_image_get_fieldref_token (assembly, f);
4295 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4296 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4297 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4298 token = mono_image_get_array_token (assembly, m);
4299 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4300 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4301 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4302 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4303 MonoReflectionType *tb = (MonoReflectionType *)obj;
4304 token = mono_metadata_token_from_dor (
4305 mono_image_typedef_or_ref (assembly, tb->type));
4307 g_error ("requested token for %s\n", klass->name);
4310 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4316 guint32 import_lookup_table;
4320 guint32 import_address_table_rva;
4328 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4330 static MonoDynamicImage*
4331 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4333 static const guchar entrycode [16] = {0xff, 0x25, 0};
4334 MonoDynamicImage *image;
4337 const char *version = mono_get_runtime_info ()->runtime_version;
4340 image = GC_MALLOC (sizeof (MonoDynamicImage));
4342 image = g_new0 (MonoDynamicImage, 1);
4345 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4347 /*g_print ("created image %p\n", image);*/
4348 /* keep in sync with image.c */
4349 image->image.name = assembly_name;
4350 image->image.assembly_name = image->image.name; /* they may be different */
4351 image->image.module_name = module_name;
4352 image->image.version = g_strdup (version);
4353 image->image.md_version_major = 1;
4354 image->image.md_version_minor = 1;
4355 image->image.dynamic = TRUE;
4357 image->image.references = g_new0 (MonoAssembly*, 1);
4358 image->image.references [0] = NULL;
4360 mono_image_init (&image->image);
4362 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4363 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4364 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4365 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4366 image->handleref = g_hash_table_new (NULL, NULL);
4367 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4368 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4369 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4370 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4371 image->gen_params = g_ptr_array_new ();
4373 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4374 string_heap_init (&image->sheap);
4375 mono_image_add_stream_data (&image->us, "", 1);
4376 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4377 /* import tables... */
4378 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4379 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4380 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4381 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4382 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4383 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4384 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4385 stream_data_align (&image->code);
4387 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4389 for (i=0; i < MONO_TABLE_NUM; ++i) {
4390 image->tables [i].next_idx = 1;
4391 image->tables [i].columns = table_sizes [i];
4394 image->image.assembly = (MonoAssembly*)assembly;
4395 image->run = assembly->run;
4396 image->save = assembly->save;
4397 image->pe_kind = 0x1; /* ILOnly */
4398 image->machine = 0x14c; /* I386 */
4400 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4406 * mono_image_basic_init:
4407 * @assembly: an assembly builder object
4409 * Create the MonoImage that represents the assembly builder and setup some
4410 * of the helper hash table and the basic metadata streams.
4413 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4415 MonoDynamicAssembly *assembly;
4416 MonoDynamicImage *image;
4417 MonoDomain *domain = mono_object_domain (assemblyb);
4419 MONO_ARCH_SAVE_REGS;
4421 if (assemblyb->dynamic_assembly)
4425 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4427 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4430 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4432 assembly->assembly.ref_count = 1;
4433 assembly->assembly.dynamic = TRUE;
4434 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4435 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4436 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4437 if (assemblyb->culture)
4438 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4440 assembly->assembly.aname.culture = g_strdup ("");
4442 if (assemblyb->version) {
4443 char *vstr = mono_string_to_utf8 (assemblyb->version);
4444 char **version = g_strsplit (vstr, ".", 4);
4445 char **parts = version;
4446 assembly->assembly.aname.major = atoi (*parts++);
4447 assembly->assembly.aname.minor = atoi (*parts++);
4448 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4449 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4451 g_strfreev (version);
4454 assembly->assembly.aname.major = 0;
4455 assembly->assembly.aname.minor = 0;
4456 assembly->assembly.aname.build = 0;
4457 assembly->assembly.aname.revision = 0;
4460 assembly->run = assemblyb->access != 2;
4461 assembly->save = assemblyb->access != 1;
4463 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4464 image->initial_image = TRUE;
4465 assembly->assembly.aname.name = image->image.name;
4466 assembly->assembly.image = &image->image;
4468 mono_domain_assemblies_lock (domain);
4469 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4470 mono_domain_assemblies_unlock (domain);
4472 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4474 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4476 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4480 calc_section_size (MonoDynamicImage *assembly)
4484 /* alignment constraints */
4485 assembly->code.index += 3;
4486 assembly->code.index &= ~3;
4487 assembly->meta_size += 3;
4488 assembly->meta_size &= ~3;
4489 assembly->resources.index += 3;
4490 assembly->resources.index &= ~3;
4492 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4493 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4496 if (assembly->win32_res) {
4497 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4499 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4500 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4504 assembly->sections [MONO_SECTION_RELOC].size = 12;
4505 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4515 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4519 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4521 ResTreeNode *t1 = (ResTreeNode*)a;
4522 ResTreeNode *t2 = (ResTreeNode*)b;
4524 return t1->id - t2->id;
4528 * resource_tree_create:
4530 * Organize the resources into a resource tree.
4532 static ResTreeNode *
4533 resource_tree_create (MonoArray *win32_resources)
4535 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4539 tree = g_new0 (ResTreeNode, 1);
4541 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4542 MonoReflectionWin32Resource *win32_res =
4543 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4547 /* FIXME: BUG: this stores managed references in unmanaged memory */
4548 lang_node = g_new0 (ResTreeNode, 1);
4549 lang_node->id = win32_res->lang_id;
4550 lang_node->win32_res = win32_res;
4552 /* Create type node if neccesary */
4554 for (l = tree->children; l; l = l->next)
4555 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4556 type_node = (ResTreeNode*)l->data;
4561 type_node = g_new0 (ResTreeNode, 1);
4562 type_node->id = win32_res->res_type;
4565 * The resource types have to be sorted otherwise
4566 * Windows Explorer can't display the version information.
4568 tree->children = g_slist_insert_sorted (tree->children,
4569 type_node, resource_tree_compare_by_id);
4572 /* Create res node if neccesary */
4574 for (l = type_node->children; l; l = l->next)
4575 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4576 res_node = (ResTreeNode*)l->data;
4581 res_node = g_new0 (ResTreeNode, 1);
4582 res_node->id = win32_res->res_id;
4583 type_node->children = g_slist_append (type_node->children, res_node);
4586 res_node->children = g_slist_append (res_node->children, lang_node);
4593 * resource_tree_encode:
4595 * Encode the resource tree into the format used in the PE file.
4598 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4601 MonoPEResourceDir dir;
4602 MonoPEResourceDirEntry dir_entry;
4603 MonoPEResourceDataEntry data_entry;
4607 * For the format of the resource directory, see the article
4608 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4612 memset (&dir, 0, sizeof (dir));
4613 memset (&dir_entry, 0, sizeof (dir_entry));
4614 memset (&data_entry, 0, sizeof (data_entry));
4616 g_assert (sizeof (dir) == 16);
4617 g_assert (sizeof (dir_entry) == 8);
4618 g_assert (sizeof (data_entry) == 16);
4620 node->offset = p - begin;
4622 /* IMAGE_RESOURCE_DIRECTORY */
4623 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4625 memcpy (p, &dir, sizeof (dir));
4628 /* Reserve space for entries */
4630 p += sizeof (dir_entry) * dir.res_id_entries;
4632 /* Write children */
4633 for (l = node->children; l; l = l->next) {
4634 ResTreeNode *child = (ResTreeNode*)l->data;
4636 if (child->win32_res) {
4638 child->offset = p - begin;
4640 /* IMAGE_RESOURCE_DATA_ENTRY */
4641 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4642 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4644 memcpy (p, &data_entry, sizeof (data_entry));
4645 p += sizeof (data_entry);
4647 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4648 p += data_entry.rde_size;
4650 resource_tree_encode (child, begin, p, &p);
4654 /* IMAGE_RESOURCE_ENTRY */
4655 for (l = node->children; l; l = l->next) {
4656 ResTreeNode *child = (ResTreeNode*)l->data;
4657 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4659 dir_entry.is_dir = child->win32_res ? 0 : 1;
4660 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4662 memcpy (entries, &dir_entry, sizeof (dir_entry));
4663 entries += sizeof (dir_entry);
4670 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4675 MonoReflectionWin32Resource *win32_res;
4678 if (!assemblyb->win32_resources)
4682 * Resources are stored in a three level tree inside the PE file.
4683 * - level one contains a node for each type of resource
4684 * - level two contains a node for each resource
4685 * - level three contains a node for each instance of a resource for a
4686 * specific language.
4689 tree = resource_tree_create (assemblyb->win32_resources);
4691 /* Estimate the size of the encoded tree */
4693 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4694 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4695 size += mono_array_length (win32_res->res_data);
4697 /* Directory structure */
4698 size += mono_array_length (assemblyb->win32_resources) * 256;
4699 p = buf = g_malloc (size);
4701 resource_tree_encode (tree, p, p, &p);
4703 g_assert (p - buf <= size);
4705 assembly->win32_res = g_malloc (p - buf);
4706 assembly->win32_res_size = p - buf;
4707 memcpy (assembly->win32_res, buf, p - buf);
4713 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4715 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4718 p += sizeof (MonoPEResourceDir);
4719 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4720 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4721 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4722 if (dir_entry->is_dir) {
4723 fixup_resource_directory (res_section, child, rva);
4725 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4726 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4729 p += sizeof (MonoPEResourceDirEntry);
4734 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4737 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4738 g_error ("WriteFile returned %d\n", GetLastError ());
4742 * mono_image_create_pefile:
4743 * @mb: a module builder object
4745 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4746 * assembly->pefile where it can be easily retrieved later in chunks.
4749 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4750 MonoMSDOSHeader *msdos;
4751 MonoDotNetHeader *header;
4752 MonoSectionTable *section;
4753 MonoCLIHeader *cli_header;
4754 guint32 size, image_size, virtual_base, text_offset;
4755 guint32 header_start, section_start, file_offset, virtual_offset;
4756 MonoDynamicImage *assembly;
4757 MonoReflectionAssemblyBuilder *assemblyb;
4758 MonoDynamicStream pefile_stream = {0};
4759 MonoDynamicStream *pefile = &pefile_stream;
4761 guint32 *rva, value;
4763 static const unsigned char msheader[] = {
4764 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4765 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4767 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4768 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4769 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4770 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4771 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4774 assemblyb = mb->assemblyb;
4776 mono_image_basic_init (assemblyb);
4777 assembly = mb->dynamic_image;
4779 assembly->pe_kind = assemblyb->pe_kind;
4780 assembly->machine = assemblyb->machine;
4781 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4782 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4784 mono_image_build_metadata (mb);
4786 if (mb->is_main && assemblyb->resources) {
4787 int len = mono_array_length (assemblyb->resources);
4788 for (i = 0; i < len; ++i)
4789 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4792 if (mb->resources) {
4793 int len = mono_array_length (mb->resources);
4794 for (i = 0; i < len; ++i)
4795 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4798 build_compressed_metadata (assembly);
4801 assembly_add_win32_resources (assembly, assemblyb);
4803 nsections = calc_section_size (assembly);
4805 /* The DOS header and stub */
4806 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4807 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
4809 /* the dotnet header */
4810 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4812 /* the section tables */
4813 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4815 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4816 virtual_offset = VIRT_ALIGN;
4819 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4820 if (!assembly->sections [i].size)
4823 file_offset += FILE_ALIGN - 1;
4824 file_offset &= ~(FILE_ALIGN - 1);
4825 virtual_offset += VIRT_ALIGN - 1;
4826 virtual_offset &= ~(VIRT_ALIGN - 1);
4828 assembly->sections [i].offset = file_offset;
4829 assembly->sections [i].rva = virtual_offset;
4831 file_offset += assembly->sections [i].size;
4832 virtual_offset += assembly->sections [i].size;
4833 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4836 file_offset += FILE_ALIGN - 1;
4837 file_offset &= ~(FILE_ALIGN - 1);
4839 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4841 /* back-patch info */
4842 msdos = (MonoMSDOSHeader*)pefile->data;
4843 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4845 header = (MonoDotNetHeader*)(pefile->data + header_start);
4846 header->pesig [0] = 'P';
4847 header->pesig [1] = 'E';
4849 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4850 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4851 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4852 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4853 if (assemblyb->pekind == 1) {
4855 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4858 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4861 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4863 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4864 header->pe.pe_major = 6;
4865 header->pe.pe_minor = 0;
4866 size = assembly->sections [MONO_SECTION_TEXT].size;
4867 size += FILE_ALIGN - 1;
4868 size &= ~(FILE_ALIGN - 1);
4869 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4870 size = assembly->sections [MONO_SECTION_RSRC].size;
4871 size += FILE_ALIGN - 1;
4872 size &= ~(FILE_ALIGN - 1);
4873 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4874 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4875 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4876 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4877 /* pe_rva_entry_point always at the beginning of the text section */
4878 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4880 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4881 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4882 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4883 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4884 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4885 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4886 size = section_start;
4887 size += FILE_ALIGN - 1;
4888 size &= ~(FILE_ALIGN - 1);
4889 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4891 size += VIRT_ALIGN - 1;
4892 size &= ~(VIRT_ALIGN - 1);
4893 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4896 // Translate the PEFileKind value to the value expected by the Windows loader
4902 // PEFileKinds.Dll == 1
4903 // PEFileKinds.ConsoleApplication == 2
4904 // PEFileKinds.WindowApplication == 3
4907 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4908 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4910 if (assemblyb->pekind == 3)
4915 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4917 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4918 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4919 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4920 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4921 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4922 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4924 /* fill data directory entries */
4926 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4927 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4929 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4930 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4932 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4933 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4934 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4935 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4936 /* patch entrypoint name */
4937 if (assemblyb->pekind == 1)
4938 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4940 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4941 /* patch imported function RVA name */
4942 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4943 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4945 /* the import table */
4946 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4947 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4948 /* patch imported dll RVA name and other entries in the dir */
4949 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4950 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4951 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4952 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4953 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4954 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4956 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
4957 value = (assembly->text_rva + assembly->imp_names_offset);
4958 *p++ = (value) & 0xff;
4959 *p++ = (value >> 8) & (0xff);
4960 *p++ = (value >> 16) & (0xff);
4961 *p++ = (value >> 24) & (0xff);
4963 /* the CLI header info */
4964 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4965 cli_header->ch_size = GUINT32_FROM_LE (72);
4966 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4967 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4968 if (assemblyb->entry_point) {
4969 guint32 table_idx = 0;
4970 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4971 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4972 table_idx = methodb->table_idx;
4974 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4976 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4978 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4980 /* The embedded managed resources */
4981 text_offset = assembly->text_rva + assembly->code.index;
4982 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4983 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4984 text_offset += assembly->resources.index;
4985 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4986 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4987 text_offset += assembly->meta_size;
4988 if (assembly->strong_name_size) {
4989 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4990 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4991 text_offset += assembly->strong_name_size;
4994 /* write the section tables and section content */
4995 section = (MonoSectionTable*)(pefile->data + section_start);
4996 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4997 static const char section_names [][7] = {
4998 ".text", ".rsrc", ".reloc"
5000 if (!assembly->sections [i].size)
5002 strcpy (section->st_name, section_names [i]);
5003 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5004 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5005 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5006 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5007 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5008 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5009 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5013 checked_write_file (file, pefile->data, pefile->index);
5015 mono_dynamic_stream_reset (pefile);
5017 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5018 if (!assembly->sections [i].size)
5021 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5022 g_error ("SetFilePointer returned %d\n", GetLastError ());
5025 case MONO_SECTION_TEXT:
5026 /* patch entry point */
5027 p = (guchar*)(assembly->code.data + 2);
5028 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5029 *p++ = (value) & 0xff;
5030 *p++ = (value >> 8) & 0xff;
5031 *p++ = (value >> 16) & 0xff;
5032 *p++ = (value >> 24) & 0xff;
5034 checked_write_file (file, assembly->code.data, assembly->code.index);
5035 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5036 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5037 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5040 g_free (assembly->image.raw_metadata);
5042 case MONO_SECTION_RELOC: {
5046 guint16 type_and_offset;
5050 g_assert (sizeof (reloc) == 12);
5052 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5053 reloc.block_size = GUINT32_FROM_LE (12);
5056 * the entrypoint is always at the start of the text section
5057 * 3 is IMAGE_REL_BASED_HIGHLOW
5058 * 2 is patch_size_rva - text_rva
5060 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5063 checked_write_file (file, &reloc, sizeof (reloc));
5067 case MONO_SECTION_RSRC:
5068 if (assembly->win32_res) {
5070 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5071 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5072 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5076 g_assert_not_reached ();
5080 /* check that the file is properly padded */
5081 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5082 g_error ("SetFilePointer returned %d\n", GetLastError ());
5083 if (! SetEndOfFile (file))
5084 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5086 mono_dynamic_stream_reset (&assembly->code);
5087 mono_dynamic_stream_reset (&assembly->us);
5088 mono_dynamic_stream_reset (&assembly->blob);
5089 mono_dynamic_stream_reset (&assembly->guid);
5090 mono_dynamic_stream_reset (&assembly->sheap);
5092 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5093 g_hash_table_destroy (assembly->blob_cache);
5094 assembly->blob_cache = NULL;
5097 MonoReflectionModule *
5098 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5102 MonoImageOpenStatus status;
5103 MonoDynamicAssembly *assembly;
5104 guint32 module_count;
5105 MonoImage **new_modules;
5106 gboolean *new_modules_loaded;
5108 name = mono_string_to_utf8 (fileName);
5110 image = mono_image_open (name, &status);
5113 if (status == MONO_IMAGE_ERROR_ERRNO)
5114 exc = mono_get_exception_file_not_found (fileName);
5116 exc = mono_get_exception_bad_image_format (name);
5118 mono_raise_exception (exc);
5123 assembly = ab->dynamic_assembly;
5124 image->assembly = (MonoAssembly*)assembly;
5126 module_count = image->assembly->image->module_count;
5127 new_modules = g_new0 (MonoImage *, module_count + 1);
5128 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5130 if (image->assembly->image->modules)
5131 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5132 if (image->assembly->image->modules_loaded)
5133 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5134 new_modules [module_count] = image;
5135 new_modules_loaded [module_count] = TRUE;
5136 mono_image_addref (image);
5138 g_free (image->assembly->image->modules);
5139 image->assembly->image->modules = new_modules;
5140 image->assembly->image->modules_loaded = new_modules_loaded;
5141 image->assembly->image->module_count ++;
5143 mono_assembly_load_references (image, &status);
5145 mono_image_close (image);
5146 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5149 return mono_module_get_object (mono_domain_get (), image);
5153 * We need to return always the same object for MethodInfo, FieldInfo etc..
5154 * but we need to consider the reflected type.
5155 * type uses a different hash, since it uses custom hash/equal functions.
5160 MonoClass *refclass;
5164 reflected_equal (gconstpointer a, gconstpointer b) {
5165 const ReflectedEntry *ea = a;
5166 const ReflectedEntry *eb = b;
5168 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5172 reflected_hash (gconstpointer a) {
5173 const ReflectedEntry *ea = a;
5174 return mono_aligned_addr_hash (ea->item);
5177 #define CHECK_OBJECT(t,p,k) \
5183 mono_domain_lock (domain); \
5184 if (!domain->refobject_hash) \
5185 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5186 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5187 mono_domain_unlock (domain); \
5190 mono_domain_unlock (domain); \
5193 #ifndef HAVE_NULL_GC
5194 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5196 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5199 #define CACHE_OBJECT(t,p,o,k) \
5202 ReflectedEntry pe; \
5204 pe.refclass = (k); \
5205 mono_domain_lock (domain); \
5206 if (!domain->refobject_hash) \
5207 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5208 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5210 ReflectedEntry *e = ALLOC_REFENTRY; \
5212 e->refclass = (k); \
5213 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5216 mono_domain_unlock (domain); \
5221 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5223 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5227 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5229 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5233 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5235 MonoDynamicImage *image = moduleb->dynamic_image;
5236 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5239 MonoImage **new_modules;
5242 * FIXME: we already created an image in mono_image_basic_init (), but
5243 * we don't know which module it belongs to, since that is only
5244 * determined at assembly save time.
5246 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5247 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5249 moduleb->module.image = &image->image;
5250 moduleb->dynamic_image = image;
5251 register_module (mono_object_domain (moduleb), moduleb, image);
5253 /* register the module with the assembly */
5254 ass = ab->dynamic_assembly->assembly.image;
5255 module_count = ass->module_count;
5256 new_modules = g_new0 (MonoImage *, module_count + 1);
5259 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5260 new_modules [module_count] = &image->image;
5261 mono_image_addref (&image->image);
5263 g_free (ass->modules);
5264 ass->modules = new_modules;
5265 ass->module_count ++;
5270 * mono_assembly_get_object:
5271 * @domain: an app domain
5272 * @assembly: an assembly
5274 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5276 MonoReflectionAssembly*
5277 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5279 static MonoClass *System_Reflection_Assembly;
5280 MonoReflectionAssembly *res;
5282 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5283 if (!System_Reflection_Assembly)
5284 System_Reflection_Assembly = mono_class_from_name (
5285 mono_defaults.corlib, "System.Reflection", "Assembly");
5286 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5287 res->assembly = assembly;
5289 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5294 MonoReflectionModule*
5295 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5297 static MonoClass *System_Reflection_Module;
5298 MonoReflectionModule *res;
5301 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5302 if (!System_Reflection_Module)
5303 System_Reflection_Module = mono_class_from_name (
5304 mono_defaults.corlib, "System.Reflection", "Module");
5305 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5308 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5310 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5311 basename = g_path_get_basename (image->name);
5312 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5313 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5317 if (image->assembly->image == image) {
5318 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5322 if (image->assembly->image->modules) {
5323 for (i = 0; i < image->assembly->image->module_count; i++) {
5324 if (image->assembly->image->modules [i] == image)
5325 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5327 g_assert (res->token);
5331 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5334 MonoReflectionModule*
5335 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5337 static MonoClass *System_Reflection_Module;
5338 MonoReflectionModule *res;
5339 MonoTableInfo *table;
5340 guint32 cols [MONO_FILE_SIZE];
5342 guint32 i, name_idx;
5345 if (!System_Reflection_Module)
5346 System_Reflection_Module = mono_class_from_name (
5347 mono_defaults.corlib, "System.Reflection", "Module");
5348 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5350 table = &image->tables [MONO_TABLE_FILE];
5351 g_assert (table_index < table->rows);
5352 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5355 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5356 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5358 /* Check whenever the row has a corresponding row in the moduleref table */
5359 table = &image->tables [MONO_TABLE_MODULEREF];
5360 for (i = 0; i < table->rows; ++i) {
5361 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5362 val = mono_metadata_string_heap (image, name_idx);
5363 if (strcmp (val, name) == 0)
5364 res->image = image->modules [i];
5367 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5368 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5369 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5370 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5371 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5377 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5379 if ((t1->type != t2->type) ||
5380 (t1->byref != t2->byref))
5384 case MONO_TYPE_VOID:
5385 case MONO_TYPE_BOOLEAN:
5386 case MONO_TYPE_CHAR:
5397 case MONO_TYPE_STRING:
5400 case MONO_TYPE_OBJECT:
5401 case MONO_TYPE_TYPEDBYREF:
5403 case MONO_TYPE_VALUETYPE:
5404 case MONO_TYPE_CLASS:
5405 case MONO_TYPE_SZARRAY:
5406 return t1->data.klass == t2->data.klass;
5408 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5409 case MONO_TYPE_ARRAY:
5410 if (t1->data.array->rank != t2->data.array->rank)
5412 return t1->data.array->eklass == t2->data.array->eklass;
5413 case MONO_TYPE_GENERICINST: {
5415 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5416 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5417 if (i1->type_argc != i2->type_argc)
5419 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5420 &t2->data.generic_class->container_class->byval_arg))
5422 /* FIXME: we should probably just compare the instance pointers directly. */
5423 for (i = 0; i < i1->type_argc; ++i) {
5424 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5430 case MONO_TYPE_MVAR:
5431 return t1->data.generic_param == t2->data.generic_param;
5433 g_error ("implement type compare for %0x!", t1->type);
5441 mymono_metadata_type_hash (MonoType *t1)
5447 hash |= t1->byref << 6; /* do not collide with t1->type values */
5449 case MONO_TYPE_VALUETYPE:
5450 case MONO_TYPE_CLASS:
5451 case MONO_TYPE_SZARRAY:
5452 /* check if the distribution is good enough */
5453 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5455 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5456 case MONO_TYPE_GENERICINST: {
5458 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5459 hash += g_str_hash (t1->data.generic_class->container_class->name);
5461 for (i = 0; i < inst->type_argc; ++i) {
5462 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5471 static MonoReflectionGenericClass*
5472 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5474 static MonoClass *System_Reflection_MonoGenericClass;
5475 MonoReflectionGenericClass *res;
5476 MonoClass *klass, *gklass;
5478 if (!System_Reflection_MonoGenericClass) {
5479 System_Reflection_MonoGenericClass = mono_class_from_name (
5480 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5481 g_assert (System_Reflection_MonoGenericClass);
5484 klass = mono_class_from_mono_type (geninst);
5485 gklass = klass->generic_class->container_class;
5487 mono_class_init (klass);
5490 /* FIXME: allow unpinned later */
5491 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5493 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5496 res->type.type = geninst;
5497 g_assert (gklass->reflection_info);
5498 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
5499 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5505 verify_safe_for_managed_space (MonoType *type)
5507 switch (type->type) {
5509 case MONO_TYPE_ARRAY:
5510 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5512 return verify_safe_for_managed_space (type->data.type);
5513 case MONO_TYPE_SZARRAY:
5514 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5515 case MONO_TYPE_GENERICINST: {
5516 MonoGenericInst *inst = type->data.generic_class->inst;
5520 for (i = 0; i < inst->type_argc; ++i)
5521 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5527 case MONO_TYPE_MVAR:
5534 * mono_type_get_object:
5535 * @domain: an app domain
5538 * Return an System.MonoType object representing the type @type.
5541 mono_type_get_object (MonoDomain *domain, MonoType *type)
5543 MonoReflectionType *res;
5544 MonoClass *klass = mono_class_from_mono_type (type);
5546 mono_domain_lock (domain);
5547 if (!domain->type_hash)
5548 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5549 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5550 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5551 mono_domain_unlock (domain);
5554 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
5555 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
5556 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5557 mono_g_hash_table_insert (domain->type_hash, type, res);
5558 mono_domain_unlock (domain);
5562 if (!verify_safe_for_managed_space (type)) {
5563 mono_domain_unlock (domain);
5564 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5567 if (klass->reflection_info && !klass->wastypebuilder) {
5568 /* g_assert_not_reached (); */
5569 /* should this be considered an error condition? */
5571 mono_domain_unlock (domain);
5572 return klass->reflection_info;
5575 mono_class_init (klass);
5577 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5579 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5582 mono_g_hash_table_insert (domain->type_hash, type, res);
5583 mono_domain_unlock (domain);
5588 * mono_method_get_object:
5589 * @domain: an app domain
5591 * @refclass: the reflected type (can be NULL)
5593 * Return an System.Reflection.MonoMethod object representing the method @method.
5595 MonoReflectionMethod*
5596 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5599 * We use the same C representation for methods and constructors, but the type
5600 * name in C# is different.
5602 static MonoClass *System_Reflection_MonoMethod = NULL;
5603 static MonoClass *System_Reflection_MonoCMethod = NULL;
5604 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5605 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5607 MonoReflectionMethod *ret;
5609 if (method->is_inflated) {
5610 MonoReflectionGenericMethod *gret;
5612 refclass = method->klass;
5613 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5614 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5615 if (!System_Reflection_MonoGenericCMethod)
5616 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5617 klass = System_Reflection_MonoGenericCMethod;
5619 if (!System_Reflection_MonoGenericMethod)
5620 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5621 klass = System_Reflection_MonoGenericMethod;
5623 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5624 gret->method.method = method;
5625 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5626 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5627 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5631 refclass = method->klass;
5633 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5634 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5635 if (!System_Reflection_MonoCMethod)
5636 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5637 klass = System_Reflection_MonoCMethod;
5640 if (!System_Reflection_MonoMethod)
5641 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5642 klass = System_Reflection_MonoMethod;
5644 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5645 ret->method = method;
5646 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5647 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5651 * mono_field_get_object:
5652 * @domain: an app domain
5656 * Return an System.Reflection.MonoField object representing the field @field
5659 MonoReflectionField*
5660 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5662 MonoReflectionField *res;
5663 static MonoClass *monofield_klass;
5665 CHECK_OBJECT (MonoReflectionField *, field, klass);
5666 if (!monofield_klass)
5667 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5668 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
5671 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5672 if (field->generic_info)
5673 res->attrs = field->generic_info->generic_type->attrs;
5675 res->attrs = field->type->attrs;
5676 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5677 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5681 * mono_property_get_object:
5682 * @domain: an app domain
5684 * @property: a property
5686 * Return an System.Reflection.MonoProperty object representing the property @property
5689 MonoReflectionProperty*
5690 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5692 MonoReflectionProperty *res;
5693 static MonoClass *monoproperty_klass;
5695 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5696 if (!monoproperty_klass)
5697 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5698 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
5700 res->property = property;
5701 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5705 * mono_event_get_object:
5706 * @domain: an app domain
5710 * Return an System.Reflection.MonoEvent object representing the event @event
5713 MonoReflectionEvent*
5714 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5716 MonoReflectionEvent *res;
5717 static MonoClass *monoevent_klass;
5719 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5720 if (!monoevent_klass)
5721 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5722 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
5725 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5729 * mono_get_reflection_missing_object:
5730 * @domain: Domain where the object lives
5732 * Returns the System.Reflection.Missing.Value singleton object
5733 * (of type System.Reflection.Missing).
5735 * Used as the value for ParameterInfo.DefaultValue when Optional
5739 mono_get_reflection_missing_object (MonoDomain *domain)
5742 static MonoClassField *missing_value_field = NULL;
5744 if (!missing_value_field) {
5745 MonoClass *missing_klass;
5746 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
5747 mono_class_init (missing_klass);
5748 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
5749 g_assert (missing_value_field);
5751 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
5757 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
5760 *dbnull = mono_get_dbnull_object (domain);
5765 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
5767 if (!*reflection_missing)
5768 *reflection_missing = mono_get_reflection_missing_object (domain);
5769 return *reflection_missing;
5773 * mono_param_get_objects:
5774 * @domain: an app domain
5777 * Return an System.Reflection.ParameterInfo array object representing the parameters
5778 * in the method @method.
5781 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5783 static MonoClass *System_Reflection_ParameterInfo;
5784 MonoArray *res = NULL;
5785 MonoReflectionMethod *member = NULL;
5786 MonoReflectionParameter *param = NULL;
5787 char **names, **blobs = NULL;
5788 guint32 *types = NULL;
5789 MonoType *type = NULL;
5790 MonoObject *dbnull = NULL;
5791 MonoObject *missing = NULL;
5792 MonoMarshalSpec **mspecs;
5793 MonoMethodSignature *sig;
5796 if (!System_Reflection_ParameterInfo)
5797 System_Reflection_ParameterInfo = mono_class_from_name (
5798 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5800 if (!mono_method_signature (method)->param_count)
5801 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5803 /* Note: the cache is based on the address of the signature into the method
5804 * since we already cache MethodInfos with the method as keys.
5806 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5808 sig = mono_method_signature (method);
5809 member = mono_method_get_object (domain, method, NULL);
5810 names = g_new (char *, sig->param_count);
5811 mono_method_get_param_names (method, (const char **) names);
5813 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5814 mono_method_get_marshal_info (method, mspecs);
5816 res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5817 for (i = 0; i < sig->param_count; ++i) {
5818 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5819 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5820 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5821 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5822 param->PositionImpl = i;
5823 param->AttrsImpl = sig->params [i]->attrs;
5825 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5826 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
5827 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
5829 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
5833 blobs = g_new0 (char *, sig->param_count);
5834 types = g_new0 (guint32, sig->param_count);
5835 get_default_param_value_blobs (method, blobs, types);
5838 /* Build MonoType for the type from the Constant Table */
5840 type = g_new0 (MonoType, 1);
5841 type->type = types [i];
5842 type->data.klass = NULL;
5843 if (types [i] == MONO_TYPE_CLASS)
5844 type->data.klass = mono_defaults.object_class;
5845 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5846 /* For enums, types [i] contains the base type */
5848 type->type = MONO_TYPE_VALUETYPE;
5849 type->data.klass = mono_class_from_mono_type (sig->params [i]);
5851 type->data.klass = mono_class_from_mono_type (type);
5853 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5855 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5856 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
5857 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
5858 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
5860 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
5866 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5868 mono_array_setref (res, i, param);
5875 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5877 mono_metadata_free_marshal_spec (mspecs [i]);
5880 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5884 * mono_method_body_get_object:
5885 * @domain: an app domain
5888 * Return an System.Reflection.MethodBody object representing the method @method.
5890 MonoReflectionMethodBody*
5891 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5893 static MonoClass *System_Reflection_MethodBody = NULL;
5894 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5895 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5896 MonoReflectionMethodBody *ret;
5897 MonoMethodNormal *mn;
5898 MonoMethodHeader *header;
5899 guint32 method_rva, local_var_sig_token;
5901 unsigned char format, flags;
5904 if (!System_Reflection_MethodBody)
5905 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5906 if (!System_Reflection_LocalVariableInfo)
5907 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5908 if (!System_Reflection_ExceptionHandlingClause)
5909 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5911 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5913 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5914 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5915 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5916 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5918 mn = (MonoMethodNormal *)method;
5919 header = mono_method_get_header (method);
5921 /* Obtain local vars signature token */
5922 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5923 ptr = mono_image_rva_map (method->klass->image, method_rva);
5924 flags = *(const unsigned char *) ptr;
5925 format = flags & METHOD_HEADER_FORMAT_MASK;
5927 case METHOD_HEADER_TINY_FORMAT:
5928 case METHOD_HEADER_TINY_FORMAT1:
5929 local_var_sig_token = 0;
5931 case METHOD_HEADER_FAT_FORMAT:
5935 local_var_sig_token = read32 (ptr);
5938 g_assert_not_reached ();
5941 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5943 ret->init_locals = header->init_locals;
5944 ret->max_stack = header->max_stack;
5945 ret->local_var_sig_token = local_var_sig_token;
5946 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5947 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5950 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5951 for (i = 0; i < header->num_locals; ++i) {
5952 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5953 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5954 info->is_pinned = header->locals [i]->pinned;
5955 info->local_index = i;
5956 mono_array_setref (ret->locals, i, info);
5960 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5961 for (i = 0; i < header->num_clauses; ++i) {
5962 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5963 MonoExceptionClause *clause = &header->clauses [i];
5965 info->flags = clause->flags;
5966 info->try_offset = clause->try_offset;
5967 info->try_length = clause->try_len;
5968 info->handler_offset = clause->handler_offset;
5969 info->handler_length = clause->handler_len;
5970 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5971 info->filter_offset = clause->data.filter_offset;
5972 else if (clause->data.catch_class)
5973 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5975 mono_array_setref (ret->clauses, i, info);
5978 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5983 * mono_get_dbnull_object:
5984 * @domain: Domain where the object lives
5986 * Returns the System.DBNull.Value singleton object
5988 * Used as the value for ParameterInfo.DefaultValue
5991 mono_get_dbnull_object (MonoDomain *domain)
5994 static MonoClassField *dbnull_value_field = NULL;
5996 if (!dbnull_value_field) {
5997 MonoClass *dbnull_klass;
5998 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5999 mono_class_init (dbnull_klass);
6000 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6001 g_assert (dbnull_value_field);
6003 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6009 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6011 guint32 param_index, i, lastp, crow = 0;
6012 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6015 MonoClass *klass = method->klass;
6016 MonoImage *image = klass->image;
6017 MonoMethodSignature *methodsig = mono_method_signature (method);
6019 MonoTableInfo *constt;
6020 MonoTableInfo *methodt;
6021 MonoTableInfo *paramt;
6023 if (!methodsig->param_count)
6026 mono_class_init (klass);
6028 if (klass->image->dynamic) {
6029 MonoReflectionMethodAux *aux;
6030 if (method->is_inflated)
6031 method = ((MonoMethodInflated*)method)->declaring;
6032 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6033 if (aux && aux->param_defaults) {
6034 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6035 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6040 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6041 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6042 constt = &image->tables [MONO_TABLE_CONSTANT];
6044 idx = mono_method_get_index (method) - 1;
6045 g_assert (idx != -1);
6047 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6048 if (idx + 1 < methodt->rows)
6049 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6051 lastp = paramt->rows + 1;
6053 for (i = param_index; i < lastp; ++i) {
6056 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6057 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6059 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6062 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6067 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6068 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6069 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6076 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6081 MonoType *basetype = type;
6086 klass = mono_class_from_mono_type (type);
6087 if (klass->valuetype) {
6088 object = mono_object_new (domain, klass);
6089 retval = ((gchar *) object + sizeof (MonoObject));
6090 if (klass->enumtype)
6091 basetype = klass->enum_basetype;
6096 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6103 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6107 memset (assembly, 0, sizeof (MonoAssemblyName));
6109 assembly->culture = "";
6110 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6112 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6115 while (g_ascii_isspace (*p) || *p == ',') {
6124 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6126 assembly->major = strtoul (p, &s, 10);
6127 if (s == p || *s != '.')
6130 assembly->minor = strtoul (p, &s, 10);
6131 if (s == p || *s != '.')
6134 assembly->build = strtoul (p, &s, 10);
6135 if (s == p || *s != '.')
6138 assembly->revision = strtoul (p, &s, 10);
6142 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6144 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6145 assembly->culture = "";
6148 assembly->culture = p;
6149 while (*p && *p != ',') {
6153 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6155 if (strncmp (p, "null", 4) == 0) {
6160 while (*p && *p != ',') {
6163 len = (p - start + 1);
6164 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6165 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6166 g_strlcpy ((char*)assembly->public_key_token, start, len);
6169 while (*p && *p != ',')
6173 while (g_ascii_isspace (*p) || *p == ',') {
6187 * mono_reflection_parse_type:
6190 * Parse a type name as accepted by the GetType () method and output the info
6191 * extracted in the info structure.
6192 * the name param will be mangled, so, make a copy before passing it to this function.
6193 * The fields in info will be valid until the memory pointed to by name is valid.
6195 * See also mono_type_get_name () below.
6197 * Returns: 0 on parse error.
6200 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6201 MonoTypeNameParse *info)
6203 char *start, *p, *w, *temp, *last_point, *startn;
6204 int in_modifiers = 0;
6205 int isbyref = 0, rank, arity = 0, i;
6207 start = p = w = name;
6209 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6210 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6211 info->name = info->name_space = NULL;
6212 info->nested = NULL;
6213 info->modifiers = NULL;
6214 info->type_arguments = NULL;
6216 /* last_point separates the namespace from the name */
6222 *p = 0; /* NULL terminate the name */
6224 info->nested = g_list_append (info->nested, startn);
6225 /* we have parsed the nesting namespace + name */
6229 info->name_space = start;
6231 info->name = last_point + 1;
6233 info->name_space = (char *)"";
6252 i = strtol (p, &temp, 10);
6269 info->name_space = start;
6271 info->name = last_point + 1;
6273 info->name_space = (char *)"";
6280 if (isbyref) /* only one level allowed by the spec */
6283 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6287 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6293 info->type_arguments = g_ptr_array_new ();
6294 for (i = 0; i < arity; i++) {
6295 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6296 gboolean fqname = FALSE;
6298 g_ptr_array_add (info->type_arguments, subinfo);
6305 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6316 while (*p && (*p != ']'))
6324 if (g_ascii_isspace (*aname)) {
6331 !assembly_name_to_aname (&subinfo->assembly, aname))
6335 if (i + 1 < arity) {
6355 else if (*p != '*') /* '*' means unknown lower bound */
6361 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6372 if (g_ascii_isspace (*p)) {
6379 return 0; /* missing assembly name */
6380 if (!assembly_name_to_aname (&info->assembly, p))
6386 if (info->assembly.name)
6389 // *w = 0; /* terminate class name */
6391 if (!info->name || !*info->name)
6395 /* add other consistency checks */
6400 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6402 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6406 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6408 gboolean type_resolve = FALSE;
6410 MonoImage *rootimage = image;
6412 if (info->assembly.name) {
6413 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6415 /* then we must load the assembly ourselve - see #60439 */
6416 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6420 image = assembly->image;
6421 } else if (!image) {
6422 image = mono_defaults.corlib;
6425 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6426 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6427 image = mono_defaults.corlib;
6428 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6435 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6442 image = mono_defaults.corlib;
6445 klass = mono_class_from_name_case (image, info->name_space, info->name);
6447 klass = mono_class_from_name (image, info->name_space, info->name);
6450 for (mod = info->nested; mod; mod = mod->next) {
6453 mono_class_init (klass);
6454 nested = klass->nested_classes;
6457 klass = nested->data;
6459 if (g_strcasecmp (klass->name, mod->data) == 0)
6462 if (strcmp (klass->name, mod->data) == 0)
6466 nested = nested->next;
6473 mono_class_init (klass);
6475 if (info->type_arguments) {
6476 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6477 MonoReflectionType *the_type;
6481 for (i = 0; i < info->type_arguments->len; i++) {
6482 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6484 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
6485 if (!type_args [i]) {
6491 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6493 instance = mono_reflection_bind_generic_parameters (
6494 the_type, info->type_arguments->len, type_args);
6500 klass = mono_class_from_mono_type (instance);
6503 for (mod = info->modifiers; mod; mod = mod->next) {
6504 modval = GPOINTER_TO_UINT (mod->data);
6505 if (!modval) { /* byref: must be last modifier */
6506 return &klass->this_arg;
6507 } else if (modval == -1) {
6508 klass = mono_ptr_class_get (&klass->byval_arg);
6509 } else { /* array rank */
6510 klass = mono_array_class_get (klass, modval);
6512 mono_class_init (klass);
6515 return &klass->byval_arg;
6519 * mono_reflection_get_type:
6520 * @image: a metadata context
6521 * @info: type description structure
6522 * @ignorecase: flag for case-insensitive string compares
6523 * @type_resolve: whenever type resolve was already tried
6525 * Build a MonoType from the type description in @info.
6530 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
6531 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
6535 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
6537 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
6541 g_assert (assembly->dynamic);
6543 /* Enumerate all modules */
6546 if (abuilder->modules) {
6547 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6548 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6549 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
6555 if (!type && abuilder->loaded_modules) {
6556 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6557 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6558 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
6568 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6571 MonoReflectionAssembly *assembly;
6575 if (image && image->dynamic)
6576 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
6578 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
6581 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6588 *type_resolve = TRUE;
6591 /* Reconstruct the type name */
6592 fullName = g_string_new ("");
6593 if (info->name_space && (info->name_space [0] != '\0'))
6594 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6596 g_string_printf (fullName, info->name);
6597 for (mod = info->nested; mod; mod = mod->next)
6598 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6600 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6602 if (assembly->assembly->dynamic)
6603 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
6605 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
6608 g_string_free (fullName, TRUE);
6613 mono_reflection_free_type_info (MonoTypeNameParse *info)
6615 g_list_free (info->modifiers);
6616 g_list_free (info->nested);
6618 if (info->type_arguments) {
6621 for (i = 0; i < info->type_arguments->len; i++) {
6622 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6624 mono_reflection_free_type_info (subinfo);
6625 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
6629 g_ptr_array_free (info->type_arguments, TRUE);
6634 * mono_reflection_type_from_name:
6636 * @image: a metadata context (can be NULL).
6638 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6639 * it defaults to get the type from @image or, if @image is NULL or loading
6640 * from it fails, uses corlib.
6644 mono_reflection_type_from_name (char *name, MonoImage *image)
6646 MonoType *type = NULL;
6647 MonoTypeNameParse info;
6650 /* Make a copy since parse_type modifies its argument */
6651 tmp = g_strdup (name);
6653 /*g_print ("requested type %s\n", str);*/
6654 if (mono_reflection_parse_type (tmp, &info)) {
6655 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6659 mono_reflection_free_type_info (&info);
6664 * mono_reflection_get_token:
6666 * Return the metadata token of OBJ which should be an object
6667 * representing a metadata element.
6670 mono_reflection_get_token (MonoObject *obj)
6675 klass = obj->vtable->klass;
6677 if (strcmp (klass->name, "MethodBuilder") == 0) {
6678 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6680 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6681 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6682 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6684 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6685 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6686 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6688 /* Call mono_image_create_token so the object gets added to the tokens hash table */
6689 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE);
6690 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6691 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6692 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6693 } else if (strcmp (klass->name, "MonoType") == 0) {
6694 MonoReflectionType *tb = (MonoReflectionType *)obj;
6695 token = mono_class_from_mono_type (tb->type)->type_token;
6696 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6697 strcmp (klass->name, "MonoMethod") == 0 ||
6698 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6699 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6700 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6701 if (m->method->is_inflated) {
6702 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6703 return inflated->declaring->token;
6705 token = m->method->token;
6707 } else if (strcmp (klass->name, "MonoField") == 0) {
6708 MonoReflectionField *f = (MonoReflectionField*)obj;
6710 if (f->field->generic_info && f->field->generic_info->reflection_info)
6711 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6713 token = mono_class_get_field_token (f->field);
6714 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6715 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6717 token = mono_class_get_property_token (p->property);
6718 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6719 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6721 token = mono_class_get_event_token (p->event);
6722 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6723 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6725 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6726 } else if (strcmp (klass->name, "Module") == 0) {
6727 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6730 } else if (strcmp (klass->name, "Assembly") == 0) {
6731 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6733 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6734 MonoException *ex = mono_get_exception_not_implemented (msg);
6736 mono_raise_exception (ex);
6743 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6745 int slen, type = t->type;
6746 MonoClass *tklass = t->data.klass;
6752 case MONO_TYPE_BOOLEAN: {
6753 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6758 case MONO_TYPE_CHAR:
6760 case MONO_TYPE_I2: {
6761 guint16 *val = g_malloc (sizeof (guint16));
6766 #if SIZEOF_VOID_P == 4
6772 case MONO_TYPE_I4: {
6773 guint32 *val = g_malloc (sizeof (guint32));
6778 #if SIZEOF_VOID_P == 8
6779 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6783 case MONO_TYPE_I8: {
6784 guint64 *val = g_malloc (sizeof (guint64));
6789 case MONO_TYPE_R8: {
6790 double *val = g_malloc (sizeof (double));
6795 case MONO_TYPE_VALUETYPE:
6796 if (t->data.klass->enumtype) {
6797 type = t->data.klass->enum_basetype->type;
6800 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6803 case MONO_TYPE_STRING:
6804 if (*p == (char)0xFF) {
6808 slen = mono_metadata_decode_value (p, &p);
6810 return mono_string_new_len (mono_domain_get (), p, slen);
6811 case MONO_TYPE_CLASS: {
6814 if (*p == (char)0xFF) {
6819 slen = mono_metadata_decode_value (p, &p);
6820 n = g_memdup (p, slen + 1);
6822 t = mono_reflection_type_from_name (n, image);
6824 g_warning ("Cannot load type '%s'", n);
6828 return mono_type_get_object (mono_domain_get (), t);
6832 case MONO_TYPE_OBJECT: {
6835 MonoClass *subc = NULL;
6840 } else if (subt == 0x0E) {
6841 type = MONO_TYPE_STRING;
6843 } else if (subt == 0x1D) {
6844 MonoType simple_type = {{0}};
6849 /* See Partition II, Appendix B3 */
6850 etype = MONO_TYPE_OBJECT;
6851 type = MONO_TYPE_SZARRAY;
6852 simple_type.type = etype;
6853 tklass = mono_class_from_mono_type (&simple_type);
6855 } else if (subt == 0x55) {
6858 slen = mono_metadata_decode_value (p, &p);
6859 n = g_memdup (p, slen + 1);
6861 t = mono_reflection_type_from_name (n, image);
6863 g_error ("Cannot load type '%s'", n);
6866 subc = mono_class_from_mono_type (t);
6867 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6868 MonoType simple_type = {{0}};
6869 simple_type.type = subt;
6870 subc = mono_class_from_mono_type (&simple_type);
6872 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6874 val = load_cattr_value (image, &subc->byval_arg, p, end);
6875 obj = mono_object_new (mono_domain_get (), subc);
6876 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6880 case MONO_TYPE_SZARRAY: {
6882 guint32 i, alen, basetype;
6885 if (alen == 0xffffffff) {
6889 arr = mono_array_new (mono_domain_get(), tklass, alen);
6890 basetype = tklass->byval_arg.type;
6891 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
6892 basetype = tklass->enum_basetype->type;
6897 case MONO_TYPE_BOOLEAN:
6898 for (i = 0; i < alen; i++) {
6899 MonoBoolean val = *p++;
6900 mono_array_set (arr, MonoBoolean, i, val);
6903 case MONO_TYPE_CHAR:
6906 for (i = 0; i < alen; i++) {
6907 guint16 val = read16 (p);
6908 mono_array_set (arr, guint16, i, val);
6915 for (i = 0; i < alen; i++) {
6916 guint32 val = read32 (p);
6917 mono_array_set (arr, guint32, i, val);
6922 for (i = 0; i < alen; i++) {
6925 mono_array_set (arr, double, i, val);
6931 for (i = 0; i < alen; i++) {
6932 guint64 val = read64 (p);
6933 mono_array_set (arr, guint64, i, val);
6937 case MONO_TYPE_CLASS:
6938 case MONO_TYPE_OBJECT:
6939 case MONO_TYPE_STRING:
6940 for (i = 0; i < alen; i++) {
6941 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6942 mono_array_setref (arr, i, item);
6946 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
6952 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6958 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6960 static MonoClass *klass;
6961 static MonoMethod *ctor;
6963 void *params [2], *unboxed;
6966 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6968 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6970 params [0] = mono_type_get_object (mono_domain_get (), t);
6972 retval = mono_object_new (mono_domain_get (), klass);
6973 unboxed = mono_object_unbox (retval);
6974 mono_runtime_invoke (ctor, unboxed, params, NULL);
6980 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6982 static MonoClass *klass;
6983 static MonoMethod *ctor;
6985 void *unboxed, *params [2];
6988 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6990 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6993 params [1] = typedarg;
6994 retval = mono_object_new (mono_domain_get (), klass);
6995 unboxed = mono_object_unbox (retval);
6996 mono_runtime_invoke (ctor, unboxed, params, NULL);
7002 type_is_reference (MonoType *type)
7004 switch (type->type) {
7005 case MONO_TYPE_BOOLEAN:
7006 case MONO_TYPE_CHAR:
7019 case MONO_TYPE_VALUETYPE:
7027 free_param_data (MonoMethodSignature *sig, void **params) {
7029 for (i = 0; i < sig->param_count; ++i) {
7030 if (!type_is_reference (sig->params [i]))
7031 g_free (params [i]);
7036 * Find the field index in the metadata FieldDef table.
7039 find_field_index (MonoClass *klass, MonoClassField *field) {
7042 for (i = 0; i < klass->field.count; ++i) {
7043 if (field == &klass->fields [i])
7044 return klass->field.first + 1 + i;
7050 * Find the property index in the metadata Property table.
7053 find_property_index (MonoClass *klass, MonoProperty *property) {
7056 for (i = 0; i < klass->property.count; ++i) {
7057 if (property == &klass->properties [i])
7058 return klass->property.first + 1 + i;
7064 * Find the event index in the metadata Event table.
7067 find_event_index (MonoClass *klass, MonoEvent *event) {
7070 for (i = 0; i < klass->event.count; ++i) {
7071 if (event == &klass->events [i])
7072 return klass->event.first + 1 + i;
7078 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7080 const char *p = (const char*)data;
7082 guint32 i, j, num_named;
7086 mono_class_init (method->klass);
7089 attr = mono_object_new (mono_domain_get (), method->klass);
7090 mono_runtime_invoke (method, attr, NULL, NULL);
7094 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7097 /*g_print ("got attr %s\n", method->klass->name);*/
7099 /* Allocate using alloca so it gets GC tracking */
7100 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7104 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7105 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7109 attr = mono_object_new (mono_domain_get (), method->klass);
7110 mono_runtime_invoke (method, attr, params, NULL);
7111 free_param_data (method->signature, params);
7112 num_named = read16 (named);
7114 for (j = 0; j < num_named; j++) {
7116 char *name, named_type, data_type;
7117 named_type = *named++;
7118 data_type = *named++; /* type of data */
7119 if (data_type == MONO_TYPE_SZARRAY)
7120 data_type = *named++;
7121 if (data_type == MONO_TYPE_ENUM) {
7124 type_len = mono_metadata_decode_blob_size (named, &named);
7125 type_name = g_malloc (type_len + 1);
7126 memcpy (type_name, named, type_len);
7127 type_name [type_len] = 0;
7129 /* FIXME: lookup the type and check type consistency */
7132 name_len = mono_metadata_decode_blob_size (named, &named);
7133 name = g_malloc (name_len + 1);
7134 memcpy (name, named, name_len);
7135 name [name_len] = 0;
7137 if (named_type == 0x53) {
7138 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7139 void *val = load_cattr_value (image, field->type, named, &named);
7140 mono_field_set_value (attr, field, val);
7141 if (!type_is_reference (field->type))
7143 } else if (named_type == 0x54) {
7146 MonoType *prop_type;
7148 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7149 /* can we have more that 1 arg in a custom attr named property? */
7150 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7151 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7152 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7153 mono_property_set_value (prop, attr, pparams, NULL);
7154 if (!type_is_reference (prop_type))
7155 g_free (pparams [0]);
7164 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7166 MonoArray *typedargs, *namedargs;
7167 MonoClass *attrklass;
7168 static MonoMethod *ctor;
7171 const char *p = (const char*)data;
7173 guint32 i, j, num_named;
7176 mono_class_init (method->klass);
7179 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7181 domain = mono_domain_get ();
7183 /* This is for Attributes with no parameters */
7184 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7185 params [0] = mono_method_get_object (domain, method, NULL);
7186 params [1] = params [2] = NULL;
7187 mono_runtime_invoke (method, attr, params, NULL);
7191 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7194 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7198 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7199 MonoObject *obj, *typedarg;
7202 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7203 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7204 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7205 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7206 mono_array_setref (typedargs, i, typedarg);
7208 if (!type_is_reference (mono_method_signature (method)->params [i]))
7213 num_named = read16 (named);
7214 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7216 attrklass = method->klass;
7217 for (j = 0; j < num_named; j++) {
7219 char *name, named_type, data_type;
7220 named_type = *named++;
7221 data_type = *named++; /* type of data */
7222 if (data_type == MONO_TYPE_SZARRAY)
7223 data_type = *named++;
7224 if (data_type == MONO_TYPE_ENUM) {
7227 type_len = mono_metadata_decode_blob_size (named, &named);
7228 type_name = g_malloc (type_len + 1);
7229 memcpy (type_name, named, type_len);
7230 type_name [type_len] = 0;
7232 /* FIXME: lookup the type and check type consistency */
7235 name_len = mono_metadata_decode_blob_size (named, &named);
7236 name = g_malloc (name_len + 1);
7237 memcpy (name, named, name_len);
7238 name [name_len] = 0;
7240 if (named_type == 0x53) {
7241 MonoObject *obj, *typedarg, *namedarg;
7242 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7243 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7245 minfo = mono_field_get_object (domain, NULL, field);
7246 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7247 typedarg = create_cattr_typed_arg (field->type, obj);
7248 namedarg = create_cattr_named_arg (minfo, typedarg);
7249 mono_array_setref (namedargs, j, namedarg);
7250 if (!type_is_reference (field->type))
7252 } else if (named_type == 0x54) {
7253 MonoObject *obj, *typedarg, *namedarg;
7254 MonoType *prop_type;
7256 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7258 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7259 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7260 minfo = mono_property_get_object (domain, NULL, prop);
7261 val = load_cattr_value (image, prop_type, named, &named);
7262 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7263 typedarg = create_cattr_typed_arg (prop_type, obj);
7264 namedarg = create_cattr_named_arg (minfo, typedarg);
7265 mono_array_setref (namedargs, j, namedarg);
7266 if (!type_is_reference (prop_type))
7271 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7272 params [0] = mono_method_get_object (domain, method, NULL);
7273 params [1] = typedargs;
7274 params [2] = namedargs;
7275 mono_runtime_invoke (ctor, attr, params, NULL);
7280 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7286 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7287 for (i = 0; i < cinfo->num_attrs; ++i) {
7288 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7289 mono_array_setref (result, i, attr);
7295 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7302 for (i = 0; i < cinfo->num_attrs; ++i) {
7303 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7307 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7309 for (i = 0; i < cinfo->num_attrs; ++i) {
7310 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7311 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7312 mono_array_setref (result, n, attr);
7320 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7326 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7327 for (i = 0; i < cinfo->num_attrs; ++i) {
7328 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7329 mono_array_setref (result, i, attr);
7335 * mono_custom_attrs_from_index:
7337 * Returns: NULL if no attributes are found or if a loading error occurs.
7340 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7342 guint32 mtoken, i, len;
7343 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7345 MonoCustomAttrInfo *ainfo;
7346 GList *tmp, *list = NULL;
7349 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7351 i = mono_metadata_custom_attrs_from_index (image, idx);
7355 while (i < ca->rows) {
7356 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7358 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7361 len = g_list_length (list);
7364 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7365 ainfo->num_attrs = len;
7366 ainfo->image = image;
7367 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7368 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7369 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7370 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7371 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7372 mtoken |= MONO_TOKEN_METHOD_DEF;
7374 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7375 mtoken |= MONO_TOKEN_MEMBER_REF;
7378 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7381 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7382 if (!ainfo->attrs [i].ctor) {
7383 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7388 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7389 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7390 ainfo->attrs [i].data = (guchar*)data;
7398 mono_custom_attrs_from_method (MonoMethod *method)
7400 MonoCustomAttrInfo *cinfo;
7403 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (method)))
7405 idx = mono_method_get_index (method);
7406 idx <<= MONO_CUSTOM_ATTR_BITS;
7407 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7408 return mono_custom_attrs_from_index (method->klass->image, idx);
7412 mono_custom_attrs_from_class (MonoClass *klass)
7414 MonoCustomAttrInfo *cinfo;
7417 if (klass->generic_class)
7418 klass = klass->generic_class->container_class;
7420 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (klass)))
7422 idx = mono_metadata_token_index (klass->type_token);
7423 idx <<= MONO_CUSTOM_ATTR_BITS;
7424 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7425 return mono_custom_attrs_from_index (klass->image, idx);
7429 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7431 MonoCustomAttrInfo *cinfo;
7434 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (assembly)))
7436 idx = 1; /* there is only one assembly */
7437 idx <<= MONO_CUSTOM_ATTR_BITS;
7438 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7439 return mono_custom_attrs_from_index (assembly->image, idx);
7442 static MonoCustomAttrInfo*
7443 mono_custom_attrs_from_module (MonoImage *image)
7445 MonoCustomAttrInfo *cinfo;
7448 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (image)))
7450 idx = 1; /* there is only one module */
7451 idx <<= MONO_CUSTOM_ATTR_BITS;
7452 idx |= MONO_CUSTOM_ATTR_MODULE;
7453 return mono_custom_attrs_from_index (image, idx);
7457 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7459 MonoCustomAttrInfo *cinfo;
7462 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (property)))
7464 idx = find_property_index (klass, property);
7465 idx <<= MONO_CUSTOM_ATTR_BITS;
7466 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7467 return mono_custom_attrs_from_index (klass->image, idx);
7471 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7473 MonoCustomAttrInfo *cinfo;
7476 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (event)))
7478 idx = find_event_index (klass, event);
7479 idx <<= MONO_CUSTOM_ATTR_BITS;
7480 idx |= MONO_CUSTOM_ATTR_EVENT;
7481 return mono_custom_attrs_from_index (klass->image, idx);
7485 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7487 MonoCustomAttrInfo *cinfo;
7490 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (field)))
7492 idx = find_field_index (klass, field);
7493 idx <<= MONO_CUSTOM_ATTR_BITS;
7494 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7495 return mono_custom_attrs_from_index (klass->image, idx);
7499 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7502 guint32 i, idx, method_index;
7503 guint32 param_list, param_last, param_pos, found;
7505 MonoReflectionMethodAux *aux;
7507 if (method->klass->image->dynamic) {
7508 MonoCustomAttrInfo *res, *ainfo;
7511 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7512 if (!aux || !aux->param_cattr)
7515 /* Need to copy since it will be freed later */
7516 ainfo = aux->param_cattr [param];
7517 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7518 res = g_malloc0 (size);
7519 memcpy (res, ainfo, size);
7523 image = method->klass->image;
7524 method_index = mono_method_get_index (method);
7525 ca = &image->tables [MONO_TABLE_METHOD];
7527 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7528 if (method_index == ca->rows) {
7529 ca = &image->tables [MONO_TABLE_PARAM];
7530 param_last = ca->rows + 1;
7532 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7533 ca = &image->tables [MONO_TABLE_PARAM];
7536 for (i = param_list; i < param_last; ++i) {
7537 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7538 if (param_pos == param) {
7546 idx <<= MONO_CUSTOM_ATTR_BITS;
7547 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7548 return mono_custom_attrs_from_index (image, idx);
7552 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7556 for (i = 0; i < ainfo->num_attrs; ++i) {
7557 klass = ainfo->attrs [i].ctor->klass;
7558 if (mono_class_has_parent (klass, attr_klass))
7565 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7572 for (i = 0; i < ainfo->num_attrs; ++i) {
7573 klass = ainfo->attrs [i].ctor->klass;
7574 if (mono_class_has_parent (klass, attr_klass)) {
7579 if (attr_index == -1)
7582 attrs = mono_custom_attrs_construct (ainfo);
7584 return mono_array_get (attrs, MonoObject*, attr_index);
7590 * mono_reflection_get_custom_attrs_info:
7591 * @obj: a reflection object handle
7593 * Return the custom attribute info for attributes defined for the
7594 * reflection handle @obj. The objects.
7597 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7600 MonoCustomAttrInfo *cinfo = NULL;
7602 klass = obj->vtable->klass;
7603 if (klass == mono_defaults.monotype_class) {
7604 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7605 klass = mono_class_from_mono_type (rtype->type);
7606 cinfo = mono_custom_attrs_from_class (klass);
7607 } else if (strcmp ("Assembly", klass->name) == 0) {
7608 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7609 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7610 } else if (strcmp ("Module", klass->name) == 0) {
7611 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7612 cinfo = mono_custom_attrs_from_module (module->image);
7613 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7614 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7615 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7616 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7617 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7618 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7619 } else if (strcmp ("MonoField", klass->name) == 0) {
7620 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7621 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7622 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7623 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7624 cinfo = mono_custom_attrs_from_method (rmethod->method);
7625 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7626 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7627 cinfo = mono_custom_attrs_from_method (rmethod->method);
7628 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7629 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7630 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7631 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7632 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7633 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7634 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7635 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7636 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7637 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7638 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7639 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7640 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7641 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7642 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7643 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7644 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7645 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7646 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7647 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7648 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7649 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7650 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
7651 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
7652 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
7653 } else { /* handle other types here... */
7654 g_error ("get custom attrs not yet supported for %s", klass->name);
7661 * mono_reflection_get_custom_attrs_by_type:
7662 * @obj: a reflection object handle
7664 * Return an array with all the custom attributes defined of the
7665 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7666 * of that type are returned. The objects are fully build. Return NULL if a loading error
7670 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7673 MonoCustomAttrInfo *cinfo;
7675 cinfo = mono_reflection_get_custom_attrs_info (obj);
7678 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7680 result = mono_custom_attrs_construct (cinfo);
7682 mono_custom_attrs_free (cinfo);
7684 if (mono_loader_get_last_error ())
7686 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
7693 * mono_reflection_get_custom_attrs:
7694 * @obj: a reflection object handle
7696 * Return an array with all the custom attributes defined of the
7697 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
7701 mono_reflection_get_custom_attrs (MonoObject *obj)
7703 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7707 * mono_reflection_get_custom_attrs_data:
7708 * @obj: a reflection obj handle
7710 * Returns an array of System.Reflection.CustomAttributeData,
7711 * which include information about attributes reflected on
7712 * types loaded using the Reflection Only methods
7715 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7718 MonoCustomAttrInfo *cinfo;
7720 cinfo = mono_reflection_get_custom_attrs_info (obj);
7722 result = mono_custom_attrs_data_construct (cinfo);
7724 mono_custom_attrs_free (cinfo);
7726 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
7731 static MonoReflectionType*
7732 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
7734 MonoMethod *method_get_underlying_system_type;
7736 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
7737 mono_class_get_method_from_name (mono_object_class (t),
7738 "get_UnderlyingSystemType",
7740 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
7744 mono_reflection_type_get_handle (MonoReflectionType* t)
7749 t = mono_reflection_type_get_underlying_system_type (t);
7757 * LOCKING: Assumes the loader lock is held.
7759 static MonoMethodSignature*
7760 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7761 MonoMethodSignature *sig;
7764 count = parameters? mono_array_length (parameters): 0;
7766 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7767 sig->param_count = count;
7768 sig->sentinelpos = -1; /* FIXME */
7769 for (i = 0; i < count; ++i) {
7770 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7771 sig->params [i] = mono_reflection_type_get_handle (pt);
7777 * LOCKING: Assumes the loader lock is held.
7779 static MonoMethodSignature*
7780 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7781 MonoMethodSignature *sig;
7783 sig = parameters_to_signature (mp, ctor->parameters);
7784 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7785 sig->ret = &mono_defaults.void_class->byval_arg;
7790 * LOCKING: Assumes the loader lock is held.
7792 static MonoMethodSignature*
7793 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7794 MonoMethodSignature *sig;
7796 sig = parameters_to_signature (mp, method->parameters);
7797 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7798 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7799 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7803 static MonoMethodSignature*
7804 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7805 MonoMethodSignature *sig;
7807 sig = parameters_to_signature (NULL, method->parameters);
7808 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7809 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7810 sig->generic_param_count = 0;
7815 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7817 MonoClass *klass = mono_object_class (prop);
7818 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7819 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7820 *name = mono_string_to_utf8 (pb->name);
7821 *type = pb->type->type;
7823 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7824 *name = g_strdup (p->property->name);
7825 if (p->property->get)
7826 *type = mono_method_signature (p->property->get)->ret;
7828 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7833 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7835 MonoClass *klass = mono_object_class (field);
7836 if (strcmp (klass->name, "FieldBuilder") == 0) {
7837 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7838 *name = mono_string_to_utf8 (fb->name);
7839 *type = fb->type->type;
7841 MonoReflectionField *f = (MonoReflectionField *)field;
7842 *name = g_strdup (f->field->name);
7843 *type = f->field->type;
7848 * Encode a value in a custom attribute stream of bytes.
7849 * The value to encode is either supplied as an object in argument val
7850 * (valuetypes are boxed), or as a pointer to the data in the
7852 * @type represents the type of the value
7853 * @buffer is the start of the buffer
7854 * @p the current position in the buffer
7855 * @buflen contains the size of the buffer and is used to return the new buffer size
7856 * if this needs to be realloced.
7857 * @retbuffer and @retp return the start and the position of the buffer
7860 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7862 MonoTypeEnum simple_type;
7864 if ((p-buffer) + 10 >= *buflen) {
7867 newbuf = g_realloc (buffer, *buflen);
7868 p = newbuf + (p-buffer);
7872 argval = ((char*)arg + sizeof (MonoObject));
7873 simple_type = type->type;
7875 switch (simple_type) {
7876 case MONO_TYPE_BOOLEAN:
7881 case MONO_TYPE_CHAR:
7884 swap_with_size (p, argval, 2, 1);
7890 swap_with_size (p, argval, 4, 1);
7894 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
7904 swap_with_size (p, argval, 8, 1);
7910 swap_with_size (p, argval, 8, 1);
7913 case MONO_TYPE_VALUETYPE:
7914 if (type->data.klass->enumtype) {
7915 simple_type = type->data.klass->enum_basetype->type;
7918 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7921 case MONO_TYPE_STRING: {
7928 str = mono_string_to_utf8 ((MonoString*)arg);
7929 slen = strlen (str);
7930 if ((p-buffer) + 10 + slen >= *buflen) {
7934 newbuf = g_realloc (buffer, *buflen);
7935 p = newbuf + (p-buffer);
7938 mono_metadata_encode_value (slen, p, &p);
7939 memcpy (p, str, slen);
7944 case MONO_TYPE_CLASS: {
7952 k = mono_object_class (arg);
7953 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7954 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
7955 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
7958 if (rt && (rtc = mono_object_class (rt)) &&
7959 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
7960 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
7961 arg = (MonoObject *) rt;
7964 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
7967 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7968 slen = strlen (str);
7969 if ((p-buffer) + 10 + slen >= *buflen) {
7973 newbuf = g_realloc (buffer, *buflen);
7974 p = newbuf + (p-buffer);
7977 mono_metadata_encode_value (slen, p, &p);
7978 memcpy (p, str, slen);
7983 case MONO_TYPE_SZARRAY: {
7985 MonoClass *eclass, *arg_eclass;
7988 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7991 len = mono_array_length ((MonoArray*)arg);
7993 *p++ = (len >> 8) & 0xff;
7994 *p++ = (len >> 16) & 0xff;
7995 *p++ = (len >> 24) & 0xff;
7997 *retbuffer = buffer;
7998 eclass = type->data.klass;
7999 arg_eclass = mono_object_class (arg)->element_class;
8002 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8003 eclass = mono_defaults.object_class;
8005 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8006 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8007 int elsize = mono_class_array_element_size (arg_eclass);
8008 for (i = 0; i < len; ++i) {
8009 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8012 } else if (eclass->valuetype && arg_eclass->valuetype) {
8013 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8014 int elsize = mono_class_array_element_size (eclass);
8015 for (i = 0; i < len; ++i) {
8016 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8020 for (i = 0; i < len; ++i) {
8021 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8026 case MONO_TYPE_OBJECT: {
8032 * The parameter type is 'object' but the type of the actual
8033 * argument is not. So we have to add type information to the blob
8034 * too. This is completely undocumented in the spec.
8038 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8043 klass = mono_object_class (arg);
8045 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8048 } else if (klass->enumtype) {
8050 } else if (klass == mono_defaults.string_class) {
8051 simple_type = MONO_TYPE_STRING;
8054 } else if (klass->rank == 1) {
8056 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8057 /* See Partition II, Appendix B3 */
8060 *p++ = klass->element_class->byval_arg.type;
8061 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8063 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8064 *p++ = simple_type = klass->byval_arg.type;
8067 g_error ("unhandled type in custom attr");
8069 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8070 slen = strlen (str);
8071 if ((p-buffer) + 10 + slen >= *buflen) {
8075 newbuf = g_realloc (buffer, *buflen);
8076 p = newbuf + (p-buffer);
8079 mono_metadata_encode_value (slen, p, &p);
8080 memcpy (p, str, slen);
8083 simple_type = klass->enum_basetype->type;
8087 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8090 *retbuffer = buffer;
8094 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8096 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8097 char *str = type_get_qualified_name (type, NULL);
8098 int slen = strlen (str);
8102 * This seems to be optional...
8105 mono_metadata_encode_value (slen, p, &p);
8106 memcpy (p, str, slen);
8109 } else if (type->type == MONO_TYPE_OBJECT) {
8111 } else if (type->type == MONO_TYPE_CLASS) {
8112 /* it should be a type: encode_cattr_value () has the check */
8115 mono_metadata_encode_value (type->type, p, &p);
8116 if (type->type == MONO_TYPE_SZARRAY)
8117 /* See the examples in Partition VI, Annex B */
8118 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8125 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8128 /* Preallocate a large enough buffer */
8129 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8130 char *str = type_get_qualified_name (type, NULL);
8133 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8134 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8140 len += strlen (name);
8142 if ((p-buffer) + 20 + len >= *buflen) {
8146 newbuf = g_realloc (buffer, *buflen);
8147 p = newbuf + (p-buffer);
8151 encode_field_or_prop_type (type, p, &p);
8153 len = strlen (name);
8154 mono_metadata_encode_value (len, p, &p);
8155 memcpy (p, name, len);
8157 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8159 *retbuffer = buffer;
8163 * mono_reflection_get_custom_attrs_blob:
8164 * @ctor: custom attribute constructor
8165 * @ctorArgs: arguments o the constructor
8171 * Creates the blob of data that needs to be saved in the metadata and that represents
8172 * the custom attributed described by @ctor, @ctorArgs etc.
8173 * Returns: a Byte array representing the blob of data.
8176 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8179 MonoMethodSignature *sig;
8184 MONO_ARCH_SAVE_REGS;
8186 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8187 /* sig is freed later so allocate it in the heap */
8188 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8190 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8193 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8195 p = buffer = g_malloc (buflen);
8196 /* write the prolog */
8199 for (i = 0; i < sig->param_count; ++i) {
8200 arg = mono_array_get (ctorArgs, MonoObject*, i);
8201 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8205 i += mono_array_length (properties);
8207 i += mono_array_length (fields);
8209 *p++ = (i >> 8) & 0xff;
8212 for (i = 0; i < mono_array_length (properties); ++i) {
8216 prop = mono_array_get (properties, gpointer, i);
8217 get_prop_name_and_type (prop, &pname, &ptype);
8218 *p++ = 0x54; /* PROPERTY signature */
8219 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8226 for (i = 0; i < mono_array_length (fields); ++i) {
8230 field = mono_array_get (fields, gpointer, i);
8231 get_field_name_and_type (field, &fname, &ftype);
8232 *p++ = 0x53; /* FIELD signature */
8233 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8238 g_assert (p - buffer <= buflen);
8239 buflen = p - buffer;
8240 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8241 p = mono_array_addr (result, char, 0);
8242 memcpy (p, buffer, buflen);
8244 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8250 static void* reflection_info_desc = NULL;
8251 #define MOVING_GC_REGISTER(addr) do { \
8252 if (!reflection_info_desc) { \
8254 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8256 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8259 #define MOVING_GC_REGISTER(addr)
8263 * mono_reflection_setup_internal_class:
8264 * @tb: a TypeBuilder object
8266 * Creates a MonoClass that represents the TypeBuilder.
8267 * This is a trick that lets us simplify a lot of reflection code
8268 * (and will allow us to support Build and Run assemblies easier).
8271 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8273 MonoClass *klass, *parent;
8275 MONO_ARCH_SAVE_REGS;
8277 mono_loader_lock ();
8280 /* check so we can compile corlib correctly */
8281 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8282 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8283 parent = tb->parent->type->data.klass;
8285 parent = my_mono_class_from_mono_type (tb->parent->type);
8291 /* the type has already being created: it means we just have to change the parent */
8292 if (tb->type.type) {
8293 klass = mono_class_from_mono_type (tb->type.type);
8294 klass->parent = NULL;
8295 /* fool mono_class_setup_parent */
8296 klass->supertypes = NULL;
8297 mono_class_setup_parent (klass, parent);
8298 mono_class_setup_mono_type (klass);
8299 mono_loader_unlock ();
8303 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8305 klass->image = &tb->module->dynamic_image->image;
8307 klass->inited = 1; /* we lie to the runtime */
8308 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8309 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8310 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8311 klass->flags = tb->attrs;
8313 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8315 klass->element_class = klass;
8317 MOVING_GC_REGISTER (&klass->reflection_info);
8318 klass->reflection_info = tb;
8320 /* Put into cache so mono_class_get () will find it */
8321 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8323 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8324 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8326 if (parent != NULL) {
8327 mono_class_setup_parent (klass, parent);
8328 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8329 const char *old_n = klass->name;
8330 /* trick to get relative numbering right when compiling corlib */
8331 klass->name = "BuildingObject";
8332 mono_class_setup_parent (klass, mono_defaults.object_class);
8333 klass->name = old_n;
8336 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8337 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8338 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8339 klass->instance_size = sizeof (MonoObject);
8340 klass->size_inited = 1;
8341 mono_class_setup_vtable_general (klass, NULL, 0);
8344 mono_class_setup_mono_type (klass);
8346 mono_class_setup_supertypes (klass);
8349 * FIXME: handle interfaces.
8352 tb->type.type = &klass->byval_arg;
8354 if (tb->nesting_type) {
8355 g_assert (tb->nesting_type->type);
8356 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8359 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8361 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8363 mono_loader_unlock ();
8367 * mono_reflection_setup_generic_class:
8368 * @tb: a TypeBuilder object
8370 * Setup the generic class before adding the first generic parameter.
8373 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8377 MONO_ARCH_SAVE_REGS;
8379 klass = my_mono_class_from_mono_type (tb->type.type);
8380 if (tb->generic_container)
8383 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8384 tb->generic_container->owner.klass = klass;
8388 * mono_reflection_create_generic_class:
8389 * @tb: a TypeBuilder object
8391 * Creates the generic class after all generic parameters have been added.
8394 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8399 MONO_ARCH_SAVE_REGS;
8401 klass = my_mono_class_from_mono_type (tb->type.type);
8403 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8405 if (klass->generic_container || (count == 0))
8408 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8410 klass->generic_container = tb->generic_container;
8412 klass->generic_container->type_argc = count;
8413 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8415 for (i = 0; i < count; i++) {
8416 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8417 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8418 g_assert (klass->generic_container->type_params [i].owner);
8421 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8425 * mono_reflection_create_internal_class:
8426 * @tb: a TypeBuilder object
8428 * Actually create the MonoClass that is associated with the TypeBuilder.
8431 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8435 MONO_ARCH_SAVE_REGS;
8437 klass = my_mono_class_from_mono_type (tb->type.type);
8439 mono_loader_lock ();
8440 if (klass->enumtype && klass->enum_basetype == NULL) {
8441 MonoReflectionFieldBuilder *fb;
8444 g_assert (tb->fields != NULL);
8445 g_assert (mono_array_length (tb->fields) >= 1);
8447 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8449 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8450 mono_loader_unlock ();
8454 klass->enum_basetype = fb->type->type;
8455 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8456 if (!klass->element_class)
8457 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8460 * get the element_class from the current corlib.
8462 ec = default_class_from_mono_type (klass->enum_basetype);
8463 klass->instance_size = ec->instance_size;
8464 klass->size_inited = 1;
8466 * this is almost safe to do with enums and it's needed to be able
8467 * to create objects of the enum type (for use in SetConstant).
8469 /* FIXME: Does this mean enums can't have method overrides ? */
8470 mono_class_setup_vtable_general (klass, NULL, 0);
8472 mono_loader_unlock ();
8475 static MonoMarshalSpec*
8476 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8477 MonoReflectionMarshal *minfo)
8479 MonoMarshalSpec *res;
8481 res = g_new0 (MonoMarshalSpec, 1);
8482 res->native = minfo->type;
8484 switch (minfo->type) {
8485 case MONO_NATIVE_LPARRAY:
8486 res->data.array_data.elem_type = minfo->eltype;
8487 if (minfo->has_size) {
8488 res->data.array_data.param_num = minfo->param_num;
8489 res->data.array_data.num_elem = minfo->count;
8490 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8493 res->data.array_data.param_num = -1;
8494 res->data.array_data.num_elem = -1;
8495 res->data.array_data.elem_mult = -1;
8499 case MONO_NATIVE_BYVALTSTR:
8500 case MONO_NATIVE_BYVALARRAY:
8501 res->data.array_data.num_elem = minfo->count;
8504 case MONO_NATIVE_CUSTOM:
8505 if (minfo->marshaltyperef)
8506 res->data.custom_data.custom_name =
8507 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8509 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8519 MonoReflectionMarshal*
8520 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8521 MonoMarshalSpec *spec)
8523 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8524 MonoReflectionMarshal *minfo;
8527 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8528 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8529 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8530 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8533 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8534 minfo->type = spec->native;
8536 switch (minfo->type) {
8537 case MONO_NATIVE_LPARRAY:
8538 minfo->eltype = spec->data.array_data.elem_type;
8539 minfo->count = spec->data.array_data.num_elem;
8540 minfo->param_num = spec->data.array_data.param_num;
8543 case MONO_NATIVE_BYVALTSTR:
8544 case MONO_NATIVE_BYVALARRAY:
8545 minfo->count = spec->data.array_data.num_elem;
8548 case MONO_NATIVE_CUSTOM:
8549 if (spec->data.custom_data.custom_name) {
8550 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8552 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8554 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8556 if (spec->data.custom_data.cookie)
8557 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8568 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8569 ReflectionMethodBuilder *rmb,
8570 MonoMethodSignature *sig)
8573 MonoMethodNormal *pm;
8574 MonoMarshalSpec **specs;
8575 MonoReflectionMethodAux *method_aux;
8581 * Methods created using a MethodBuilder should have their memory allocated
8582 * inside the image mempool, while dynamic methods should have their memory
8585 dynamic = rmb->refs != NULL;
8586 mp = dynamic ? NULL : klass->image->mempool;
8589 g_assert (!klass->generic_class);
8591 mono_loader_lock ();
8593 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8594 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8595 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8597 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8599 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8601 pm = (MonoMethodNormal*)m;
8603 m->dynamic = dynamic;
8605 m->flags = rmb->attrs;
8606 m->iflags = rmb->iattrs;
8607 m->name = mp_string_to_utf8 (mp, rmb->name);
8610 m->skip_visibility = rmb->skip_visibility;
8612 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8614 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8615 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8618 m->signature->pinvoke = 1;
8619 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8620 m->signature->pinvoke = 1;
8622 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8624 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8625 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8627 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8629 if (klass->image->dynamic)
8630 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8632 mono_loader_unlock ();
8635 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8636 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8637 MonoMethodHeader *header;
8639 gint32 max_stack, i;
8640 gint32 num_locals = 0;
8641 gint32 num_clauses = 0;
8645 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8646 code_size = rmb->ilgen->code_len;
8647 max_stack = rmb->ilgen->max_stack;
8648 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8649 if (rmb->ilgen->ex_handlers)
8650 num_clauses = method_count_clauses (rmb->ilgen);
8653 code = mono_array_addr (rmb->code, guint8, 0);
8654 code_size = mono_array_length (rmb->code);
8655 /* we probably need to run a verifier on the code... */
8665 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8666 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8667 header->code_size = code_size;
8668 header->code = mp_g_malloc (mp, code_size);
8669 memcpy ((char*)header->code, code, code_size);
8670 header->max_stack = max_stack;
8671 header->init_locals = rmb->init_locals;
8672 header->num_locals = num_locals;
8674 for (i = 0; i < num_locals; ++i) {
8675 MonoReflectionLocalBuilder *lb =
8676 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8678 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8679 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8682 header->num_clauses = num_clauses;
8684 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8685 rmb->ilgen, num_clauses);
8688 pm->header = header;
8691 if (rmb->generic_params) {
8692 int count = mono_array_length (rmb->generic_params);
8693 MonoGenericContainer *container;
8695 m->generic_container = container = rmb->generic_container;
8696 container->type_argc = count;
8697 container->type_params = g_new0 (MonoGenericParam, count);
8698 container->owner.method = m;
8700 for (i = 0; i < count; i++) {
8701 MonoReflectionGenericParam *gp =
8702 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8704 container->type_params [i] = *gp->type.type->data.generic_param;
8707 if (klass->generic_container) {
8708 container->parent = klass->generic_container;
8709 container->context.class_inst = klass->generic_container->context.class_inst;
8711 container->context.method_inst = mono_get_shared_generic_inst (container);
8715 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8719 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8721 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8722 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8723 for (i = 0; i < rmb->nrefs; ++i)
8724 data [i + 1] = rmb->refs [i];
8729 /* Parameter info */
8732 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8733 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8734 for (i = 0; i <= m->signature->param_count; ++i) {
8735 MonoReflectionParamBuilder *pb;
8736 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8737 if ((i > 0) && (pb->attrs)) {
8738 /* Make a copy since it might point to a shared type structure */
8739 /* FIXME: Alloc this from a mempool */
8740 m->signature->params [i - 1] = mono_metadata_type_dup (NULL, m->signature->params [i - 1]);
8741 m->signature->params [i - 1]->attrs = pb->attrs;
8744 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8745 MonoDynamicImage *assembly;
8746 guint32 idx, def_type, len;
8750 if (!method_aux->param_defaults) {
8751 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8752 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8754 assembly = (MonoDynamicImage*)klass->image;
8755 idx = encode_constant (assembly, pb->def_value, &def_type);
8756 /* Copy the data from the blob since it might get realloc-ed */
8757 p = assembly->blob.data + idx;
8758 len = mono_metadata_decode_blob_size (p, &p2);
8760 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8761 method_aux->param_default_types [i] = def_type;
8762 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8766 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
8768 if (!method_aux->param_cattr)
8769 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8770 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8776 /* Parameter marshalling */
8779 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8780 MonoReflectionParamBuilder *pb;
8781 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8782 if (pb->marshal_info) {
8784 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8785 specs [pb->position] =
8786 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8790 if (specs != NULL) {
8792 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8793 method_aux->param_marshall = specs;
8796 if (klass->image->dynamic && method_aux)
8797 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8799 mono_loader_unlock ();
8805 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8807 ReflectionMethodBuilder rmb;
8808 MonoMethodSignature *sig;
8810 mono_loader_lock ();
8811 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8812 mono_loader_unlock ();
8814 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8816 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8817 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8819 /* If we are in a generic class, we might be called multiple times from inflate_method */
8820 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
8821 /* ilgen is no longer needed */
8829 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8831 ReflectionMethodBuilder rmb;
8832 MonoMethodSignature *sig;
8834 mono_loader_lock ();
8835 sig = method_builder_to_signature (klass->image->mempool, mb);
8836 mono_loader_unlock ();
8838 reflection_methodbuilder_from_method_builder (&rmb, mb);
8840 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8841 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8843 /* If we are in a generic class, we might be called multiple times from inflate_method */
8844 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
8845 /* ilgen is no longer needed */
8851 static MonoClassField*
8852 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8854 MonoClassField *field;
8858 field = g_new0 (MonoClassField, 1);
8860 field->name = mono_string_to_utf8 (fb->name);
8862 /* FIXME: handle type modifiers */
8863 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8864 field->type->attrs = fb->attrs;
8866 field->type = fb->type->type;
8868 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8869 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8870 if (fb->offset != -1)
8871 field->offset = fb->offset;
8872 field->parent = klass;
8873 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8875 if (fb->def_value) {
8876 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8877 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8878 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8879 /* Copy the data from the blob since it might get realloc-ed */
8880 p = assembly->blob.data + idx;
8881 len = mono_metadata_decode_blob_size (p, &p2);
8883 field->data = g_malloc (len);
8884 memcpy ((gpointer)field->data, p, len);
8891 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8894 MonoReflectionTypeBuilder *tb = NULL;
8895 gboolean is_dynamic = FALSE;
8899 mono_loader_lock ();
8901 domain = mono_object_domain (type);
8903 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8904 tb = (MonoReflectionTypeBuilder *) type;
8907 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8908 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8910 tb = rgi->generic_type;
8914 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
8915 if (tb && tb->generic_container)
8916 mono_reflection_create_generic_class (tb);
8918 klass = mono_class_from_mono_type (type->type);
8919 if (!klass->generic_container) {
8920 mono_loader_unlock ();
8924 if (klass->wastypebuilder) {
8925 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8930 mono_loader_unlock ();
8932 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
8934 return &geninst->byval_arg;
8938 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
8940 MonoGenericClass *gclass;
8941 MonoGenericInst *inst;
8943 g_assert (klass->generic_container);
8945 inst = mono_metadata_get_generic_inst (type_argc, types);
8946 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
8948 return mono_generic_class_get_class (gclass);
8951 MonoReflectionMethod*
8952 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8955 MonoMethod *method, *inflated;
8956 MonoMethodInflated *imethod;
8957 MonoReflectionMethodBuilder *mb = NULL;
8958 MonoGenericContext tmp_context;
8959 MonoGenericInst *ginst;
8960 MonoType **type_argv;
8963 MONO_ARCH_SAVE_REGS;
8964 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8965 MonoReflectionTypeBuilder *tb;
8968 mb = (MonoReflectionMethodBuilder *) rmethod;
8969 tb = (MonoReflectionTypeBuilder *) mb->type;
8970 klass = mono_class_from_mono_type (tb->type.type);
8972 method = methodbuilder_to_mono_method (klass, mb);
8974 method = rmethod->method;
8977 klass = method->klass;
8979 if (method->is_inflated)
8980 method = ((MonoMethodInflated *) method)->declaring;
8982 count = mono_method_signature (method)->generic_param_count;
8983 if (count != mono_array_length (types))
8986 type_argv = g_new0 (MonoType *, count);
8987 for (i = 0; i < count; i++) {
8988 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8989 type_argv [i] = garg->type;
8991 ginst = mono_metadata_get_generic_inst (count, type_argv);
8994 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
8995 tmp_context.method_inst = ginst;
8997 inflated = mono_class_inflate_generic_method (method, &tmp_context);
8998 imethod = (MonoMethodInflated *) inflated;
9000 MOVING_GC_REGISTER (&imethod->reflection_info);
9001 imethod->reflection_info = rmethod;
9003 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9007 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
9009 MonoMethodInflated *imethod;
9010 MonoGenericContext tmp_context;
9011 MonoGenericContext *context;
9014 klass = mono_class_from_mono_type (type->type.type);
9015 g_assert (klass->generic_class);
9016 context = mono_class_get_context (klass);
9018 if (method->generic_container) {
9019 g_assert (method->klass == klass->generic_class->container_class);
9021 tmp_context.class_inst = klass->generic_class->context.class_inst;
9022 tmp_context.method_inst = method->generic_container->context.method_inst;
9023 context = &tmp_context;
9026 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9027 if (method->generic_container) {
9028 MOVING_GC_REGISTER (&imethod->reflection_info);
9029 imethod->reflection_info = obj;
9031 return (MonoMethod *) imethod;
9035 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9040 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9042 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9043 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9044 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9045 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9046 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9047 method = ((MonoReflectionMethod *) obj)->method;
9049 method = NULL; /* prevent compiler warning */
9050 g_assert_not_reached ();
9053 return inflate_mono_method (type, method, obj);
9057 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9058 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9061 MonoGenericClass *gclass;
9062 MonoDynamicGenericClass *dgclass;
9063 MonoClass *klass, *gklass;
9066 MONO_ARCH_SAVE_REGS;
9068 klass = mono_class_from_mono_type (type->type.type);
9069 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9070 gclass = type->type.type->data.generic_class;
9072 g_assert (gclass->is_dynamic);
9073 dgclass = (MonoDynamicGenericClass *) gclass;
9075 if (dgclass->initialized)
9078 gklass = gclass->container_class;
9079 mono_class_init (gklass);
9081 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9082 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9083 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9084 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9085 dgclass->count_events = events ? mono_array_length (events) : 0;
9087 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9088 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9089 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9090 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9091 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9093 for (i = 0; i < dgclass->count_methods; i++) {
9094 MonoObject *obj = mono_array_get (methods, gpointer, i);
9096 dgclass->methods [i] = inflate_method (type, obj);
9099 for (i = 0; i < dgclass->count_ctors; i++) {
9100 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9102 dgclass->ctors [i] = inflate_method (type, obj);
9105 for (i = 0; i < dgclass->count_fields; i++) {
9106 MonoObject *obj = mono_array_get (fields, gpointer, i);
9107 MonoClassField *field;
9108 MonoInflatedField *ifield;
9110 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9111 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9112 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9113 field = ((MonoReflectionField *) obj)->field;
9115 field = NULL; /* prevent compiler warning */
9116 g_assert_not_reached ();
9119 ifield = g_new0 (MonoInflatedField, 1);
9120 ifield->generic_type = field->type;
9121 MOVING_GC_REGISTER (&ifield->reflection_info);
9122 ifield->reflection_info = obj;
9124 dgclass->fields [i] = *field;
9125 dgclass->fields [i].parent = klass;
9126 dgclass->fields [i].generic_info = ifield;
9127 dgclass->fields [i].type = mono_class_inflate_generic_type (
9128 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9131 for (i = 0; i < dgclass->count_properties; i++) {
9132 MonoObject *obj = mono_array_get (properties, gpointer, i);
9133 MonoProperty *property = &dgclass->properties [i];
9135 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9136 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9138 property->parent = klass;
9139 property->attrs = pb->attrs;
9140 property->name = mono_string_to_utf8 (pb->name);
9142 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9144 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9145 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9146 *property = *((MonoReflectionProperty *) obj)->property;
9149 property->get = inflate_mono_method (type, property->get, NULL);
9151 property->set = inflate_mono_method (type, property->set, NULL);
9153 g_assert_not_reached ();
9156 for (i = 0; i < dgclass->count_events; i++) {
9157 MonoObject *obj = mono_array_get (events, gpointer, i);
9158 MonoEvent *event = &dgclass->events [i];
9160 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9161 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9163 event->parent = klass;
9164 event->attrs = eb->attrs;
9165 event->name = mono_string_to_utf8 (eb->name);
9167 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9168 if (eb->remove_method)
9169 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9170 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9171 *event = *((MonoReflectionEvent *) obj)->event;
9174 event->add = inflate_mono_method (type, event->add, NULL);
9176 event->remove = inflate_mono_method (type, event->remove, NULL);
9178 g_assert_not_reached ();
9181 dgclass->initialized = TRUE;
9185 ensure_runtime_vtable (MonoClass *klass)
9187 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9190 if (!tb || klass->wastypebuilder)
9193 ensure_runtime_vtable (klass->parent);
9195 num = tb->ctors? mono_array_length (tb->ctors): 0;
9196 num += tb->num_methods;
9197 klass->method.count = num;
9198 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9199 num = tb->ctors? mono_array_length (tb->ctors): 0;
9200 for (i = 0; i < num; ++i)
9201 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9202 num = tb->num_methods;
9204 for (i = 0; i < num; ++i)
9205 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9207 if (tb->interfaces) {
9208 klass->interface_count = mono_array_length (tb->interfaces);
9209 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9210 for (i = 0; i < klass->interface_count; ++i) {
9211 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9212 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9216 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9217 for (i = 0; i < klass->method.count; ++i)
9218 klass->methods [i]->slot = i;
9220 mono_class_setup_interface_offsets (klass);
9224 * The generic vtable is needed even if image->run is not set since some
9225 * runtime code like ves_icall_Type_GetMethodsByName depends on
9226 * method->slot being defined.
9230 * tb->methods could not be freed since it is used for determining
9231 * overrides during dynamic vtable construction.
9236 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9238 MonoReflectionTypeBuilder *tb;
9244 g_assert (klass->image->dynamic);
9246 if (!klass->reflection_info)
9249 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9251 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9255 for (i = 0; i < tb->num_methods; ++i) {
9256 MonoReflectionMethodBuilder *mb =
9257 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9258 if (mb->override_method)
9264 *overrides = g_new0 (MonoMethod*, onum * 2);
9267 for (i = 0; i < tb->num_methods; ++i) {
9268 MonoReflectionMethodBuilder *mb =
9269 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9270 if (mb->override_method) {
9271 (*overrides) [onum * 2] =
9272 mb->override_method->method;
9273 (*overrides) [onum * 2 + 1] =
9276 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9277 g_assert (mb->override_method->method);
9278 g_assert (mb->mhandle);
9285 *num_overrides = onum;
9289 typebuilder_setup_fields (MonoClass *klass)
9291 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9292 MonoReflectionFieldBuilder *fb;
9293 MonoClassField *field;
9298 klass->field.count = tb->num_fields;
9299 klass->field.first = 0;
9301 if (!klass->field.count)
9304 klass->fields = g_new0 (MonoClassField, klass->field.count);
9306 for (i = 0; i < klass->field.count; ++i) {
9307 fb = mono_array_get (tb->fields, gpointer, i);
9308 field = &klass->fields [i];
9309 field->name = mono_string_to_utf8 (fb->name);
9311 /* FIXME: handle type modifiers */
9312 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9313 field->type->attrs = fb->attrs;
9315 field->type = fb->type->type;
9317 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9318 field->data = mono_array_addr (fb->rva_data, char, 0);
9319 if (fb->offset != -1)
9320 field->offset = fb->offset;
9321 field->parent = klass;
9323 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9325 if (fb->def_value) {
9326 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9327 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9328 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9329 /* Copy the data from the blob since it might get realloc-ed */
9330 p = assembly->blob.data + idx;
9331 len = mono_metadata_decode_blob_size (p, &p2);
9333 field->data = g_malloc (len);
9334 memcpy ((gpointer)field->data, p, len);
9337 mono_class_layout_fields (klass);
9341 typebuilder_setup_properties (MonoClass *klass)
9343 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9344 MonoReflectionPropertyBuilder *pb;
9347 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9348 klass->property.first = 0;
9350 klass->properties = g_new0 (MonoProperty, klass->property.count);
9351 for (i = 0; i < klass->property.count; ++i) {
9352 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9353 klass->properties [i].parent = klass;
9354 klass->properties [i].attrs = pb->attrs;
9355 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9357 klass->properties [i].get = pb->get_method->mhandle;
9359 klass->properties [i].set = pb->set_method->mhandle;
9361 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9365 MonoReflectionEvent *
9366 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9368 MonoEvent *event = g_new0 (MonoEvent, 1);
9372 klass = my_mono_class_from_mono_type (tb->type.type);
9374 event->parent = klass;
9375 event->attrs = eb->attrs;
9376 event->name = mono_string_to_utf8 (eb->name);
9378 event->add = eb->add_method->mhandle;
9379 if (eb->remove_method)
9380 event->remove = eb->remove_method->mhandle;
9381 if (eb->raise_method)
9382 event->raise = eb->raise_method->mhandle;
9384 if (eb->other_methods) {
9385 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9386 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9387 MonoReflectionMethodBuilder *mb =
9388 mono_array_get (eb->other_methods,
9389 MonoReflectionMethodBuilder*, j);
9390 event->other [j] = mb->mhandle;
9394 return mono_event_get_object (mono_object_domain (tb), klass, event);
9398 typebuilder_setup_events (MonoClass *klass)
9400 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9401 MonoReflectionEventBuilder *eb;
9404 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9405 klass->event.first = 0;
9407 klass->events = g_new0 (MonoEvent, klass->event.count);
9408 for (i = 0; i < klass->event.count; ++i) {
9409 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9410 klass->events [i].parent = klass;
9411 klass->events [i].attrs = eb->attrs;
9412 klass->events [i].name = mono_string_to_utf8 (eb->name);
9414 klass->events [i].add = eb->add_method->mhandle;
9415 if (eb->remove_method)
9416 klass->events [i].remove = eb->remove_method->mhandle;
9417 if (eb->raise_method)
9418 klass->events [i].raise = eb->raise_method->mhandle;
9420 if (eb->other_methods) {
9421 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9422 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9423 MonoReflectionMethodBuilder *mb =
9424 mono_array_get (eb->other_methods,
9425 MonoReflectionMethodBuilder*, j);
9426 klass->events [i].other [j] = mb->mhandle;
9433 remove_instantiations_of (gpointer key,
9437 MonoType *type = (MonoType*)key;
9438 MonoClass *klass = (MonoClass*)user_data;
9440 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
9447 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9451 MonoReflectionType* res;
9454 MONO_ARCH_SAVE_REGS;
9456 domain = mono_object_domain (tb);
9457 klass = my_mono_class_from_mono_type (tb->type.type);
9459 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9462 * we need to lock the domain because the lock will be taken inside
9463 * So, we need to keep the locking order correct.
9465 mono_domain_lock (domain);
9466 mono_loader_lock ();
9467 if (klass->wastypebuilder) {
9468 mono_loader_unlock ();
9469 mono_domain_unlock (domain);
9470 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9473 * Fields to set in klass:
9474 * the various flags: delegate/unicode/contextbound etc.
9476 klass->flags = tb->attrs;
9477 klass->has_cctor = 1;
9478 klass->has_finalize = 1;
9481 if (!((MonoDynamicImage*)klass->image)->run) {
9482 if (klass->generic_container) {
9483 /* FIXME: The code below can't handle generic classes */
9484 klass->wastypebuilder = TRUE;
9485 mono_loader_unlock ();
9486 mono_domain_unlock (domain);
9487 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9492 /* enums are done right away */
9493 if (!klass->enumtype)
9494 ensure_runtime_vtable (klass);
9497 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9498 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9499 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9503 /* fields and object layout */
9504 if (klass->parent) {
9505 if (!klass->parent->size_inited)
9506 mono_class_init (klass->parent);
9507 klass->instance_size = klass->parent->instance_size;
9508 klass->sizes.class_size = 0;
9509 klass->min_align = klass->parent->min_align;
9510 /* if the type has no fields we won't call the field_setup
9511 * routine which sets up klass->has_references.
9513 klass->has_references |= klass->parent->has_references;
9515 klass->instance_size = sizeof (MonoObject);
9516 klass->min_align = 1;
9519 /* FIXME: handle packing_size and instance_size */
9520 typebuilder_setup_fields (klass);
9522 typebuilder_setup_properties (klass);
9524 typebuilder_setup_events (klass);
9526 klass->wastypebuilder = TRUE;
9529 * If we are a generic TypeBuilder, there might be instantiations in the type cache
9530 * which have type System.Reflection.MonoGenericClass, but after the type is created,
9531 * we want to return normal System.MonoType objects, so clear these out from the cache.
9533 if (domain->type_hash && klass->generic_container)
9534 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
9536 mono_loader_unlock ();
9537 mono_domain_unlock (domain);
9539 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
9540 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
9541 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
9544 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9545 g_assert (res != (MonoReflectionType*)tb);
9551 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9553 MonoGenericParam *param;
9556 MONO_ARCH_SAVE_REGS;
9558 param = g_new0 (MonoGenericParam, 1);
9560 if (gparam->mbuilder) {
9561 if (!gparam->mbuilder->generic_container) {
9562 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9563 gparam->mbuilder->generic_container->is_method = TRUE;
9565 param->owner = gparam->mbuilder->generic_container;
9566 } else if (gparam->tbuilder) {
9567 g_assert (gparam->tbuilder->generic_container);
9568 param->owner = gparam->tbuilder->generic_container;
9571 param->name = mono_string_to_utf8 (gparam->name);
9572 param->num = gparam->index;
9574 image = &gparam->tbuilder->module->dynamic_image->image;
9575 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9577 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
9578 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9580 gparam->type.type = g_new0 (MonoType, 1);
9581 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9582 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9583 gparam->type.type->data.generic_param = param;
9587 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9589 MonoDynamicImage *assembly = sig->module->dynamic_image;
9590 guint32 na = mono_array_length (sig->arguments);
9595 sigbuffer_init (&buf, 32);
9597 sigbuffer_add_value (&buf, 0x07);
9598 sigbuffer_add_value (&buf, na);
9599 for (i = 0; i < na; ++i) {
9600 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9601 encode_reflection_type (assembly, type, &buf);
9604 buflen = buf.p - buf.buf;
9605 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9606 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9607 sigbuffer_free (&buf);
9613 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9615 MonoDynamicImage *assembly = sig->module->dynamic_image;
9616 guint32 na = mono_array_length (sig->arguments);
9621 sigbuffer_init (&buf, 32);
9623 sigbuffer_add_value (&buf, 0x06);
9624 for (i = 0; i < na; ++i) {
9625 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9626 encode_reflection_type (assembly, type, &buf);
9629 buflen = buf.p - buf.buf;
9630 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9631 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9632 sigbuffer_free (&buf);
9638 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9640 ReflectionMethodBuilder rmb;
9641 MonoMethodSignature *sig;
9646 sig = dynamic_method_to_signature (mb);
9648 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9651 * Resolve references.
9654 * Every second entry in the refs array is reserved for storing handle_class,
9655 * which is needed by the ldtoken implementation in the JIT.
9657 rmb.nrefs = mb->nrefs;
9658 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9659 for (i = 0; i < mb->nrefs; i += 2) {
9660 MonoClass *handle_class;
9662 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
9664 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9665 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9667 * The referenced DynamicMethod should already be created by the managed
9668 * code, except in the case of circular references. In that case, we store
9669 * method in the refs array, and fix it up later when the referenced
9670 * DynamicMethod is created.
9672 if (method->mhandle) {
9673 ref = method->mhandle;
9675 /* FIXME: GC object stored in unmanaged memory */
9678 /* FIXME: GC object stored in unmanaged memory */
9679 method->referenced_by = g_slist_append (method->referenced_by, mb);
9681 handle_class = mono_defaults.methodhandle_class;
9683 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
9686 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9691 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9692 rmb.refs [i + 1] = handle_class;
9695 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
9697 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9699 /* Fix up refs entries pointing at us */
9700 for (l = mb->referenced_by; l; l = l->next) {
9701 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
9702 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
9705 g_assert (method->mhandle);
9707 data = (gpointer*)wrapper->method_data;
9708 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
9709 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
9710 data [i + 1] = mb->mhandle;
9713 g_slist_free (mb->referenced_by);
9717 /* ilgen is no longer needed */
9722 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
9727 mono_runtime_free_method (
9728 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
9732 * mono_reflection_lookup_dynamic_token:
9734 * Finish the Builder object pointed to by TOKEN and return the corresponding
9735 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
9736 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
9740 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
9742 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9746 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9749 g_assert_not_reached ();
9755 handle_class = &klass;
9756 return resolve_object (image, obj, handle_class, context);
9760 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
9762 gpointer result = NULL;
9764 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9765 result = mono_string_intern ((MonoString*)obj);
9766 *handle_class = NULL;
9768 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9769 MonoReflectionType *tb = (MonoReflectionType*)obj;
9771 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
9772 result = mono_class_from_mono_type (inflated);
9773 mono_metadata_free_type (inflated);
9775 result = mono_class_from_mono_type (tb->type);
9777 *handle_class = mono_defaults.typehandle_class;
9779 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9780 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9781 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9782 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9783 result = ((MonoReflectionMethod*)obj)->method;
9784 result = mono_class_inflate_generic_method (result, context);
9785 *handle_class = mono_defaults.methodhandle_class;
9787 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9788 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9789 result = mb->mhandle;
9791 /* Type is not yet created */
9792 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9794 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9797 * Hopefully this has been filled in by calling CreateType() on the
9801 * TODO: This won't work if the application finishes another
9802 * TypeBuilder instance instead of this one.
9804 result = mb->mhandle;
9806 result = mono_class_inflate_generic_method (result, context);
9807 *handle_class = mono_defaults.methodhandle_class;
9808 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9809 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9811 result = cb->mhandle;
9813 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9815 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9816 result = cb->mhandle;
9818 result = mono_class_inflate_generic_method (result, context);
9819 *handle_class = mono_defaults.methodhandle_class;
9820 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9821 result = ((MonoReflectionField*)obj)->field;
9822 *handle_class = mono_defaults.fieldhandle_class;
9824 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9825 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9826 result = fb->handle;
9829 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9831 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9832 result = fb->handle;
9835 if (fb->handle && fb->handle->parent->generic_container) {
9836 MonoClass *klass = fb->handle->parent;
9837 MonoClass *inflated = mono_class_from_mono_type (mono_class_inflate_generic_type (&klass->byval_arg, context));
9839 result = mono_class_get_field_from_name (inflated, fb->handle->name);
9842 *handle_class = mono_defaults.fieldhandle_class;
9843 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9844 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9847 klass = tb->type.type->data.klass;
9848 if (klass->wastypebuilder) {
9849 /* Already created */
9853 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9854 result = tb->type.type->data.klass;
9857 *handle_class = mono_defaults.typehandle_class;
9858 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9859 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9860 MonoMethodSignature *sig;
9863 if (helper->arguments)
9864 nargs = mono_array_length (helper->arguments);
9868 sig = mono_metadata_signature_alloc (image, nargs);
9869 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9870 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9872 if (helper->call_conv == 0) /* unmanaged */
9873 sig->call_convention = helper->unmanaged_call_conv - 1;
9875 if (helper->call_conv & 0x02)
9876 sig->call_convention = MONO_CALL_VARARG;
9878 sig->call_convention = MONO_CALL_DEFAULT;
9880 sig->param_count = nargs;
9881 /* TODO: Copy type ? */
9882 sig->ret = helper->return_type->type;
9883 for (i = 0; i < nargs; ++i) {
9884 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9885 sig->params [i] = rt->type;
9889 *handle_class = NULL;
9890 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9891 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9892 /* Already created by the managed code */
9893 g_assert (method->mhandle);
9894 result = method->mhandle;
9895 *handle_class = mono_defaults.methodhandle_class;
9896 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
9897 MonoReflectionType *tb = (MonoReflectionType*)obj;
9898 result = mono_class_from_mono_type (mono_class_inflate_generic_type (tb->type, context));
9899 *handle_class = mono_defaults.typehandle_class;
9901 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
9902 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
9903 result = mono_class_from_mono_type (mono_class_inflate_generic_type (ref->type.type, context));
9904 *handle_class = mono_defaults.typehandle_class;
9907 g_print (obj->vtable->klass->name);
9908 g_assert_not_reached ();
9914 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9915 const static guint32 declsec_flags_map[] = {
9916 0x00000000, /* empty */
9917 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9918 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9919 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9920 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9921 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9922 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9923 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9924 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9925 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9926 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9927 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9928 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9929 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9930 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9931 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9932 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9933 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9934 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9938 * Returns flags that includes all available security action associated to the handle.
9939 * @token: metadata token (either for a class or a method)
9940 * @image: image where resides the metadata.
9943 mono_declsec_get_flags (MonoImage *image, guint32 token)
9945 int index = mono_metadata_declsec_from_index (image, token);
9946 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9951 /* HasSecurity can be present for other, not specially encoded, attributes,
9952 e.g. SuppressUnmanagedCodeSecurityAttribute */
9956 for (i = index; i < t->rows; i++) {
9957 guint32 cols [MONO_DECL_SECURITY_SIZE];
9959 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9960 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9963 action = cols [MONO_DECL_SECURITY_ACTION];
9964 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9965 result |= declsec_flags_map [action];
9967 g_assert_not_reached ();
9974 * Get the security actions (in the form of flags) associated with the specified method.
9976 * @method: The method for which we want the declarative security flags.
9977 * Return the declarative security flags for the method (only).
9979 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9980 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9983 mono_declsec_flags_from_method (MonoMethod *method)
9985 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9986 /* FIXME: No cache (for the moment) */
9987 guint32 idx = mono_method_get_index (method);
9988 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9989 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9990 return mono_declsec_get_flags (method->klass->image, idx);
9996 * Get the security actions (in the form of flags) associated with the specified class.
9998 * @klass: The class for which we want the declarative security flags.
9999 * Return the declarative security flags for the class.
10001 * Note: We cache the flags inside the MonoClass structure as this will get
10002 * called very often (at least for each method).
10005 mono_declsec_flags_from_class (MonoClass *klass)
10007 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10008 if (!klass->declsec_flags) {
10009 guint32 idx = mono_metadata_token_index (klass->type_token);
10010 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10011 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10012 /* we cache the flags on classes */
10013 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10015 return klass->declsec_flags;
10021 * Get the security actions (in the form of flags) associated with the specified assembly.
10023 * @assembly: The assembly for which we want the declarative security flags.
10024 * Return the declarative security flags for the assembly.
10027 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10029 guint32 idx = 1; /* there is only one assembly */
10030 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10031 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10032 return mono_declsec_get_flags (assembly->image, idx);
10037 * Fill actions for the specific index (which may either be an encoded class token or
10038 * an encoded method token) from the metadata image.
10039 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10042 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10043 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10045 MonoBoolean result = FALSE;
10047 guint32 cols [MONO_DECL_SECURITY_SIZE];
10048 int index = mono_metadata_declsec_from_index (image, token);
10051 t = &image->tables [MONO_TABLE_DECLSECURITY];
10052 for (i = index; i < t->rows; i++) {
10053 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10055 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10058 /* if present only replace (class) permissions with method permissions */
10059 /* if empty accept either class or method permissions */
10060 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10061 if (!actions->demand.blob) {
10062 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10063 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10064 actions->demand.blob = (char*) (blob + 2);
10065 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10068 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10069 if (!actions->noncasdemand.blob) {
10070 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10071 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10072 actions->noncasdemand.blob = (char*) (blob + 2);
10073 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10076 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10077 if (!actions->demandchoice.blob) {
10078 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10079 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10080 actions->demandchoice.blob = (char*) (blob + 2);
10081 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10091 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
10092 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10094 guint32 idx = mono_metadata_token_index (klass->type_token);
10095 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10096 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10097 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
10101 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
10102 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10104 guint32 idx = mono_method_get_index (method);
10105 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10106 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10107 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10111 * Collect all actions (that requires to generate code in mini) assigned for
10112 * the specified method.
10113 * Note: Don't use the content of actions if the function return FALSE.
10116 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10118 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
10119 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10120 MonoBoolean result = FALSE;
10123 /* quick exit if no declarative security is present in the metadata */
10124 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10127 /* we want the original as the wrapper is "free" of the security informations */
10128 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10129 method = mono_marshal_method_from_wrapper (method);
10134 /* First we look for method-level attributes */
10135 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10136 mono_class_init (method->klass);
10137 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10139 result = mono_declsec_get_method_demands_params (method, demands,
10140 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10143 /* Here we use (or create) the class declarative cache to look for demands */
10144 flags = mono_declsec_flags_from_class (method->klass);
10145 if (flags & mask) {
10147 mono_class_init (method->klass);
10148 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10150 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10151 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10154 /* The boolean return value is used as a shortcut in case nothing needs to
10155 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10161 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10163 * Note: Don't use the content of actions if the function return FALSE.
10166 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10168 MonoBoolean result = FALSE;
10171 /* quick exit if no declarative security is present in the metadata */
10172 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10175 /* we want the original as the wrapper is "free" of the security informations */
10176 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10177 method = mono_marshal_method_from_wrapper (method);
10182 /* results are independant - zeroize both */
10183 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10184 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10186 /* First we look for method-level attributes */
10187 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10188 mono_class_init (method->klass);
10190 result = mono_declsec_get_method_demands_params (method, cmethod,
10191 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10194 /* Here we use (or create) the class declarative cache to look for demands */
10195 flags = mono_declsec_flags_from_class (method->klass);
10196 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10197 mono_class_init (method->klass);
10199 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10200 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10207 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10209 * @klass The inherited class - this is the class that provides the security check (attributes)
10211 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10213 * Note: Don't use the content of actions if the function return FALSE.
10216 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10218 MonoBoolean result = FALSE;
10221 /* quick exit if no declarative security is present in the metadata */
10222 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10225 /* Here we use (or create) the class declarative cache to look for demands */
10226 flags = mono_declsec_flags_from_class (klass);
10227 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10228 mono_class_init (klass);
10229 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10231 result |= mono_declsec_get_class_demands_params (klass, demands,
10232 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10239 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10241 * Note: Don't use the content of actions if the function return FALSE.
10244 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10246 /* quick exit if no declarative security is present in the metadata */
10247 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10250 /* we want the original as the wrapper is "free" of the security informations */
10251 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10252 method = mono_marshal_method_from_wrapper (method);
10257 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10258 mono_class_init (method->klass);
10259 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10261 return mono_declsec_get_method_demands_params (method, demands,
10262 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10269 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10271 guint32 cols [MONO_DECL_SECURITY_SIZE];
10275 int index = mono_metadata_declsec_from_index (image, token);
10279 t = &image->tables [MONO_TABLE_DECLSECURITY];
10280 for (i = index; i < t->rows; i++) {
10281 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10283 /* shortcut - index are ordered */
10284 if (token != cols [MONO_DECL_SECURITY_PARENT])
10287 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10288 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10289 entry->blob = (char*) (metadata + 2);
10290 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10299 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10301 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10302 guint32 idx = mono_method_get_index (method);
10303 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10304 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10305 return get_declsec_action (method->klass->image, idx, action, entry);
10311 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10314 guint32 flags = mono_declsec_flags_from_class (klass);
10315 if (declsec_flags_map [action] & flags) {
10316 guint32 idx = mono_metadata_token_index (klass->type_token);
10317 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10318 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10319 return get_declsec_action (klass->image, idx, action, entry);
10325 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10327 guint32 idx = 1; /* there is only one assembly */
10328 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10329 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10331 return get_declsec_action (assembly->image, idx, action, entry);
10335 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10337 MonoObject *res, *exc;
10339 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10340 static MonoMethod *method = NULL;
10342 if (!System_Reflection_Emit_TypeBuilder) {
10343 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10344 g_assert (System_Reflection_Emit_TypeBuilder);
10346 if (method == NULL) {
10347 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10352 * The result of mono_type_get_object () might be a System.MonoType but we
10353 * need a TypeBuilder so use klass->reflection_info.
10355 g_assert (klass->reflection_info);
10356 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10358 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10360 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10364 return *(MonoBoolean*)mono_object_unbox (res);