2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
15 #include "mono/utils/mono-digest.h"
16 #include "mono/utils/mono-membar.h"
17 #include "mono/metadata/reflection.h"
18 #include "mono/metadata/tabledefs.h"
19 #include "mono/metadata/metadata-internals.h"
20 #include <mono/metadata/profiler-private.h>
21 #include "mono/metadata/class-internals.h"
22 #include "mono/metadata/gc-internal.h"
23 #include "mono/metadata/tokentype.h"
24 #include "mono/metadata/domain-internals.h"
25 #include "mono/metadata/opcodes.h"
26 #include "mono/metadata/assembly.h"
27 #include "mono/metadata/object-internals.h"
28 #include <mono/metadata/exception.h>
29 #include <mono/metadata/marshal.h>
30 #include <mono/metadata/security-manager.h>
39 #include "mono-endian.h"
40 #include <mono/metadata/gc-internal.h>
41 #include <mono/metadata/mempool-internals.h>
44 static void* reflection_info_desc = NULL;
45 #define MOVING_GC_REGISTER(addr) do { \
46 if (!reflection_info_desc) { \
48 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
50 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
53 #define MOVING_GC_REGISTER(addr)
62 #define TEXT_OFFSET 512
63 #define CLI_H_SIZE 136
64 #define FILE_ALIGN 512
65 #define VIRT_ALIGN 8192
66 #define START_TEXT_RVA 0x00002000
69 MonoReflectionILGen *ilgen;
70 MonoReflectionType *rtype;
71 MonoArray *parameters;
72 MonoArray *generic_params;
73 MonoGenericContainer *generic_container;
79 guint32 *table_idx; /* note: it's a pointer */
83 MonoBoolean init_locals;
84 MonoBoolean skip_visibility;
85 MonoArray *return_modreq;
86 MonoArray *return_modopt;
87 MonoArray *param_modreq;
88 MonoArray *param_modopt;
89 MonoArray *permissions;
94 int charset, extra_flags, native_cc;
95 MonoString *dll, *dllentry;
96 } ReflectionMethodBuilder;
100 MonoReflectionGenericParam *gparam;
101 } GenericParamTableEntry;
103 const unsigned char table_sizes [MONO_TABLE_NUM] = {
113 MONO_INTERFACEIMPL_SIZE,
114 MONO_MEMBERREF_SIZE, /* 0x0A */
116 MONO_CUSTOM_ATTR_SIZE,
117 MONO_FIELD_MARSHAL_SIZE,
118 MONO_DECL_SECURITY_SIZE,
119 MONO_CLASS_LAYOUT_SIZE,
120 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
121 MONO_STAND_ALONE_SIGNATURE_SIZE,
125 MONO_PROPERTY_MAP_SIZE,
128 MONO_METHOD_SEMA_SIZE,
129 MONO_METHODIMPL_SIZE,
130 MONO_MODULEREF_SIZE, /* 0x1A */
136 MONO_ASSEMBLY_SIZE, /* 0x20 */
137 MONO_ASSEMBLY_PROCESSOR_SIZE,
138 MONO_ASSEMBLYOS_SIZE,
139 MONO_ASSEMBLYREF_SIZE,
140 MONO_ASSEMBLYREFPROC_SIZE,
141 MONO_ASSEMBLYREFOS_SIZE,
145 MONO_NESTED_CLASS_SIZE,
147 MONO_GENERICPARAM_SIZE, /* 0x2A */
148 MONO_METHODSPEC_SIZE,
149 MONO_GENPARCONSTRAINT_SIZE
153 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
154 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
155 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
156 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
157 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
158 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
159 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
160 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
161 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
162 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
163 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
164 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
165 static void ensure_runtime_vtable (MonoClass *klass);
166 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
167 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
168 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
169 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
170 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
171 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
172 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
173 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
175 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
176 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
177 static CRITICAL_SECTION reflection_mutex;
180 mono_reflection_init (void)
182 InitializeCriticalSection (&reflection_mutex);
186 sigbuffer_init (SigBuffer *buf, int size)
188 buf->buf = g_malloc (size);
190 buf->end = buf->buf + size;
194 sigbuffer_make_room (SigBuffer *buf, int size)
196 if (buf->end - buf->p < size) {
197 int new_size = buf->end - buf->buf + size + 32;
198 char *p = g_realloc (buf->buf, new_size);
199 size = buf->p - buf->buf;
202 buf->end = buf->buf + new_size;
207 sigbuffer_add_value (SigBuffer *buf, guint32 val)
209 sigbuffer_make_room (buf, 6);
210 mono_metadata_encode_value (val, buf->p, &buf->p);
214 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
216 sigbuffer_make_room (buf, 1);
222 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
224 sigbuffer_make_room (buf, size);
225 memcpy (buf->p, p, size);
230 sigbuffer_free (SigBuffer *buf)
238 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
242 mp_g_malloc (MonoMemPool *mp, guint size)
245 return mono_mempool_alloc (mp, size);
247 return g_malloc (size);
253 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
257 mp_g_malloc0 (MonoMemPool *mp, guint size)
260 return mono_mempool_alloc0 (mp, size);
262 return g_malloc0 (size);
268 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
269 * memory from the C heap.
272 mp_string_to_utf8 (MonoMemPool *mp, MonoString *s)
275 return mono_string_to_utf8_mp (mp, s);
277 return mono_string_to_utf8 (s);
280 #define mp_g_new(mp,struct_type, n_structs) \
281 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
283 #define mp_g_new0(mp,struct_type, n_structs) \
284 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
287 alloc_table (MonoDynamicTable *table, guint nrows)
290 g_assert (table->columns);
291 if (nrows + 1 >= table->alloc_rows) {
292 while (nrows + 1 >= table->alloc_rows) {
293 if (table->alloc_rows == 0)
294 table->alloc_rows = 16;
296 table->alloc_rows *= 2;
299 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
304 make_room_in_stream (MonoDynamicStream *stream, int size)
306 if (size <= stream->alloc_size)
309 while (stream->alloc_size <= size) {
310 if (stream->alloc_size < 4096)
311 stream->alloc_size = 4096;
313 stream->alloc_size *= 2;
316 stream->data = g_realloc (stream->data, stream->alloc_size);
320 string_heap_insert (MonoDynamicStream *sh, const char *str)
324 gpointer oldkey, oldval;
326 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
327 return GPOINTER_TO_UINT (oldval);
329 len = strlen (str) + 1;
332 make_room_in_stream (sh, idx + len);
335 * We strdup the string even if we already copy them in sh->data
336 * so that the string pointers in the hash remain valid even if
337 * we need to realloc sh->data. We may want to avoid that later.
339 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
340 memcpy (sh->data + idx, str, len);
346 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
348 char *name = mono_string_to_utf8 (str);
350 idx = string_heap_insert (sh, name);
356 string_heap_init (MonoDynamicStream *sh)
359 sh->alloc_size = 4096;
360 sh->data = g_malloc (4096);
361 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
362 string_heap_insert (sh, "");
366 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
370 make_room_in_stream (stream, stream->index + len);
371 memcpy (stream->data + stream->index, data, len);
373 stream->index += len;
375 * align index? Not without adding an additional param that controls it since
376 * we may store a blob value in pieces.
382 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
386 make_room_in_stream (stream, stream->index + len);
387 memset (stream->data + stream->index, 0, len);
389 stream->index += len;
394 stream_data_align (MonoDynamicStream *stream)
397 guint32 count = stream->index % 4;
399 /* we assume the stream data will be aligned */
401 mono_image_add_stream_data (stream, buf, 4 - count);
405 mono_blob_entry_hash (const char* str)
409 len = mono_metadata_decode_blob_size (str, &str);
413 for (str += 1; str < end; str++)
414 h = (h << 5) - h + *str;
422 mono_blob_entry_equal (const char *str1, const char *str2) {
426 len = mono_metadata_decode_blob_size (str1, &end1);
427 len2 = mono_metadata_decode_blob_size (str2, &end2);
430 return memcmp (end1, end2, len) == 0;
434 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
438 gpointer oldkey, oldval;
440 copy = g_malloc (s1+s2);
441 memcpy (copy, b1, s1);
442 memcpy (copy + s1, b2, s2);
443 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
445 idx = GPOINTER_TO_UINT (oldval);
447 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
448 mono_image_add_stream_data (&assembly->blob, b2, s2);
449 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
455 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
459 guint32 size = buf->p - buf->buf;
461 g_assert (size <= (buf->end - buf->buf));
462 mono_metadata_encode_value (size, b, &b);
463 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
467 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
468 * dest may be misaligned.
471 swap_with_size (char *dest, const char* val, int len, int nelem) {
472 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
475 for (elem = 0; elem < nelem; ++elem) {
501 g_assert_not_reached ();
507 memcpy (dest, val, len * nelem);
512 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
516 guint32 idx = 0, len;
518 len = str->length * 2;
519 mono_metadata_encode_value (len, b, &b);
520 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
522 char *swapped = g_malloc (2 * mono_string_length (str));
523 const char *p = (const char*)mono_string_chars (str);
525 swap_with_size (swapped, p, 2, mono_string_length (str));
526 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
530 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
535 /* modified version needed to handle building corlib */
537 my_mono_class_from_mono_type (MonoType *type) {
538 switch (type->type) {
539 case MONO_TYPE_ARRAY:
541 case MONO_TYPE_SZARRAY:
542 case MONO_TYPE_GENERICINST:
543 return mono_class_from_mono_type (type);
546 g_assert (type->data.generic_param->pklass);
547 return type->data.generic_param->pklass;
549 /* should be always valid when we reach this case... */
550 return type->data.klass;
555 default_class_from_mono_type (MonoType *type)
557 switch (type->type) {
558 case MONO_TYPE_OBJECT:
559 return mono_defaults.object_class;
561 return mono_defaults.void_class;
562 case MONO_TYPE_BOOLEAN:
563 return mono_defaults.boolean_class;
565 return mono_defaults.char_class;
567 return mono_defaults.sbyte_class;
569 return mono_defaults.byte_class;
571 return mono_defaults.int16_class;
573 return mono_defaults.uint16_class;
575 return mono_defaults.int32_class;
577 return mono_defaults.uint32_class;
579 return mono_defaults.int_class;
581 return mono_defaults.uint_class;
583 return mono_defaults.int64_class;
585 return mono_defaults.uint64_class;
587 return mono_defaults.single_class;
589 return mono_defaults.double_class;
590 case MONO_TYPE_STRING:
591 return mono_defaults.string_class;
593 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
594 g_assert_not_reached ();
601 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
604 MonoGenericInst *class_inst;
609 class_inst = gclass->context.class_inst;
611 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
612 klass = gclass->container_class;
613 sigbuffer_add_value (buf, klass->byval_arg.type);
614 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
616 sigbuffer_add_value (buf, class_inst->type_argc);
617 for (i = 0; i < class_inst->type_argc; ++i)
618 encode_type (assembly, class_inst->type_argv [i], buf);
623 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
626 g_assert_not_reached ();
631 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
635 case MONO_TYPE_BOOLEAN:
649 case MONO_TYPE_STRING:
650 case MONO_TYPE_OBJECT:
651 case MONO_TYPE_TYPEDBYREF:
652 sigbuffer_add_value (buf, type->type);
655 sigbuffer_add_value (buf, type->type);
656 encode_type (assembly, type->data.type, buf);
658 case MONO_TYPE_SZARRAY:
659 sigbuffer_add_value (buf, type->type);
660 encode_type (assembly, &type->data.klass->byval_arg, buf);
662 case MONO_TYPE_VALUETYPE:
663 case MONO_TYPE_CLASS: {
664 MonoClass *k = mono_class_from_mono_type (type);
666 if (k->generic_container) {
667 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
668 encode_generic_class (assembly, gclass, buf);
671 * Make sure we use the correct type.
673 sigbuffer_add_value (buf, k->byval_arg.type);
675 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
676 * otherwise two typerefs could point to the same type, leading to
677 * verification errors.
679 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
683 case MONO_TYPE_ARRAY:
684 sigbuffer_add_value (buf, type->type);
685 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
686 sigbuffer_add_value (buf, type->data.array->rank);
687 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
688 sigbuffer_add_value (buf, 0);
690 case MONO_TYPE_GENERICINST:
691 encode_generic_class (assembly, type->data.generic_class, buf);
695 sigbuffer_add_value (buf, type->type);
696 sigbuffer_add_value (buf, type->data.generic_param->num);
699 g_error ("need to encode type %x", type->type);
704 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
707 sigbuffer_add_value (buf, MONO_TYPE_VOID);
712 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
713 encode_type (assembly, type->type, buf);
717 g_assert_not_reached ();
722 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
727 for (i = 0; i < mono_array_length (modreq); ++i) {
728 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
729 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
730 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
734 for (i = 0; i < mono_array_length (modopt); ++i) {
735 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
736 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
737 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
743 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
747 guint32 nparams = sig->param_count;
753 sigbuffer_init (&buf, 32);
755 * FIXME: vararg, explicit_this, differenc call_conv values...
757 idx = sig->call_convention;
759 idx |= 0x20; /* hasthis */
760 if (sig->generic_param_count)
761 idx |= 0x10; /* generic */
762 sigbuffer_add_byte (&buf, idx);
763 if (sig->generic_param_count)
764 sigbuffer_add_value (&buf, sig->generic_param_count);
765 sigbuffer_add_value (&buf, nparams);
766 encode_type (assembly, sig->ret, &buf);
767 for (i = 0; i < nparams; ++i) {
768 if (i == sig->sentinelpos)
769 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
770 encode_type (assembly, sig->params [i], &buf);
772 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
773 sigbuffer_free (&buf);
778 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
781 * FIXME: reuse code from method_encode_signature().
785 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
786 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
787 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
790 sigbuffer_init (&buf, 32);
791 /* LAMESPEC: all the call conv spec is foobared */
792 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
793 if (mb->call_conv & 2)
794 idx |= 0x5; /* vararg */
795 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
796 idx |= 0x20; /* hasthis */
798 idx |= 0x10; /* generic */
799 sigbuffer_add_byte (&buf, idx);
801 sigbuffer_add_value (&buf, ngparams);
802 sigbuffer_add_value (&buf, nparams + notypes);
803 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
804 encode_reflection_type (assembly, mb->rtype, &buf);
805 for (i = 0; i < nparams; ++i) {
806 MonoArray *modreq = NULL;
807 MonoArray *modopt = NULL;
808 MonoReflectionType *pt;
810 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
811 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
812 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
813 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
814 encode_custom_modifiers (assembly, modreq, modopt, &buf);
815 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
816 encode_reflection_type (assembly, pt, &buf);
819 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
820 for (i = 0; i < notypes; ++i) {
821 MonoReflectionType *pt;
823 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
824 encode_reflection_type (assembly, pt, &buf);
827 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
828 sigbuffer_free (&buf);
833 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
835 MonoDynamicTable *table;
837 guint32 idx, sig_idx;
838 guint nl = mono_array_length (ilgen->locals);
842 sigbuffer_init (&buf, 32);
843 sigbuffer_add_value (&buf, 0x07);
844 sigbuffer_add_value (&buf, nl);
845 for (i = 0; i < nl; ++i) {
846 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
849 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
851 encode_reflection_type (assembly, lb->type, &buf);
853 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
854 sigbuffer_free (&buf);
856 if (assembly->standalonesig_cache == NULL)
857 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
858 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
862 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
863 idx = table->next_idx ++;
865 alloc_table (table, table->rows);
866 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
868 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
870 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
876 method_count_clauses (MonoReflectionILGen *ilgen)
878 guint32 num_clauses = 0;
881 MonoILExceptionInfo *ex_info;
882 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
883 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
884 if (ex_info->handlers)
885 num_clauses += mono_array_length (ex_info->handlers);
893 static MonoExceptionClause*
894 method_encode_clauses (MonoMemPool *mp, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
896 MonoExceptionClause *clauses;
897 MonoExceptionClause *clause;
898 MonoILExceptionInfo *ex_info;
899 MonoILExceptionBlock *ex_block;
900 guint32 finally_start;
901 int i, j, clause_index;;
903 clauses = mp_g_new0 (mp, MonoExceptionClause, num_clauses);
906 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
907 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
908 finally_start = ex_info->start + ex_info->len;
909 if (!ex_info->handlers)
911 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
912 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
913 clause = &(clauses [clause_index]);
915 clause->flags = ex_block->type;
916 clause->try_offset = ex_info->start;
918 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
919 clause->try_len = finally_start - ex_info->start;
921 clause->try_len = ex_info->len;
922 clause->handler_offset = ex_block->start;
923 clause->handler_len = ex_block->len;
924 if (ex_block->extype) {
925 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
927 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
928 clause->data.filter_offset = ex_block->filter_offset;
930 clause->data.filter_offset = 0;
932 finally_start = ex_block->start + ex_block->len;
942 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
948 gint32 num_locals = 0;
949 gint32 num_exception = 0;
952 char fat_header [12];
955 guint32 local_sig = 0;
956 guint32 header_size = 12;
959 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
960 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
964 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
966 code = mb->ilgen->code;
967 code_size = mb->ilgen->code_len;
968 max_stack = mb->ilgen->max_stack;
969 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
970 if (mb->ilgen->ex_handlers)
971 num_exception = method_count_clauses (mb->ilgen);
975 char *name = mono_string_to_utf8 (mb->name);
976 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
977 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
980 mono_raise_exception (exception);
983 code_size = mono_array_length (code);
984 max_stack = 8; /* we probably need to run a verifier on the code... */
987 stream_data_align (&assembly->code);
989 /* check for exceptions, maxstack, locals */
990 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
992 if (code_size < 64 && !(code_size & 1)) {
993 flags = (code_size << 2) | 0x2;
994 } else if (code_size < 32 && (code_size & 1)) {
995 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
999 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1000 /* add to the fixup todo list */
1001 if (mb->ilgen && mb->ilgen->num_token_fixups)
1002 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1003 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1004 return assembly->text_rva + idx;
1008 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1010 * FIXME: need to set also the header size in fat_flags.
1011 * (and more sects and init locals flags)
1015 fat_flags |= METHOD_HEADER_MORE_SECTS;
1016 if (mb->init_locals)
1017 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1018 fat_header [0] = fat_flags;
1019 fat_header [1] = (header_size / 4 ) << 4;
1020 short_value = GUINT16_TO_LE (max_stack);
1021 memcpy (fat_header + 2, &short_value, 2);
1022 int_value = GUINT32_TO_LE (code_size);
1023 memcpy (fat_header + 4, &int_value, 4);
1024 int_value = GUINT32_TO_LE (local_sig);
1025 memcpy (fat_header + 8, &int_value, 4);
1026 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1027 /* add to the fixup todo list */
1028 if (mb->ilgen && mb->ilgen->num_token_fixups)
1029 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1031 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1032 if (num_exception) {
1033 unsigned char sheader [4];
1034 MonoILExceptionInfo * ex_info;
1035 MonoILExceptionBlock * ex_block;
1038 stream_data_align (&assembly->code);
1039 /* always use fat format for now */
1040 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1041 num_exception *= 6 * sizeof (guint32);
1042 num_exception += 4; /* include the size of the header */
1043 sheader [1] = num_exception & 0xff;
1044 sheader [2] = (num_exception >> 8) & 0xff;
1045 sheader [3] = (num_exception >> 16) & 0xff;
1046 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1047 /* fat header, so we are already aligned */
1049 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1050 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1051 if (ex_info->handlers) {
1052 int finally_start = ex_info->start + ex_info->len;
1053 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1055 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1057 val = GUINT32_TO_LE (ex_block->type);
1058 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1060 val = GUINT32_TO_LE (ex_info->start);
1061 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1062 /* need fault, too, probably */
1063 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1064 val = GUINT32_TO_LE (finally_start - ex_info->start);
1066 val = GUINT32_TO_LE (ex_info->len);
1067 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1068 /* handler offset */
1069 val = GUINT32_TO_LE (ex_block->start);
1070 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1072 val = GUINT32_TO_LE (ex_block->len);
1073 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1074 finally_start = ex_block->start + ex_block->len;
1075 if (ex_block->extype) {
1076 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1078 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1079 val = ex_block->filter_offset;
1083 val = GUINT32_TO_LE (val);
1084 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1085 /*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",
1086 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);*/
1089 g_error ("No clauses for ex info block %d", i);
1093 return assembly->text_rva + idx;
1097 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1100 MonoDynamicTable *table;
1103 table = &assembly->tables [table_idx];
1105 g_assert (col < table->columns);
1107 values = table->values + table->columns;
1108 for (i = 1; i <= table->rows; ++i) {
1109 if (values [col] == token)
1111 values += table->columns;
1117 * LOCKING: Acquires the loader lock.
1119 static MonoCustomAttrInfo*
1120 lookup_custom_attr (MonoImage *image, gpointer member)
1122 MonoCustomAttrInfo* res;
1124 mono_loader_lock ();
1125 res = mono_property_hash_lookup (image->property_hash, member, MONO_PROP_DYNAMIC_CATTR);
1126 mono_loader_unlock ();
1131 return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1135 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1137 /* FIXME: Need to do more checks */
1138 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1139 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1141 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1148 static MonoCustomAttrInfo*
1149 mono_custom_attrs_from_builders (MonoMemPool *mp, MonoImage *image, MonoArray *cattrs)
1151 int i, index, count, not_visible;
1152 MonoCustomAttrInfo *ainfo;
1153 MonoReflectionCustomAttr *cattr;
1157 /* FIXME: check in assembly the Run flag is set */
1159 count = mono_array_length (cattrs);
1161 /* Skip nonpublic attributes since MS.NET seems to do the same */
1162 /* FIXME: This needs to be done more globally */
1164 for (i = 0; i < count; ++i) {
1165 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1166 if (!custom_attr_visible (image, cattr))
1169 count -= not_visible;
1171 ainfo = mp_g_malloc0 (mp, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1173 ainfo->image = image;
1174 ainfo->num_attrs = count;
1175 ainfo->cached = mp != NULL;
1177 mono_loader_lock ();
1178 for (i = 0; i < count; ++i) {
1179 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1180 if (custom_attr_visible (image, cattr)) {
1181 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1182 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1183 ainfo->attrs [index].ctor = cattr->ctor->method;
1184 ainfo->attrs [index].data = saved;
1185 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1189 mono_loader_unlock ();
1195 * LOCKING: Acquires the loader lock.
1198 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1200 MonoCustomAttrInfo *ainfo, *tmp;
1202 if (!cattrs || !mono_array_length (cattrs))
1205 ainfo = mono_custom_attrs_from_builders (image->mempool, image, cattrs);
1206 mono_loader_lock ();
1207 tmp = mono_property_hash_lookup (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR);
1209 mono_custom_attrs_free (tmp);
1210 mono_property_hash_insert (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1211 mono_loader_unlock ();
1215 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1222 * idx is the table index of the object
1223 * type is one of MONO_CUSTOM_ATTR_*
1226 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1228 MonoDynamicTable *table;
1229 MonoReflectionCustomAttr *cattr;
1231 guint32 count, i, token;
1233 char *p = blob_size;
1235 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1238 count = mono_array_length (cattrs);
1239 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1240 table->rows += count;
1241 alloc_table (table, table->rows);
1242 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1243 idx <<= MONO_CUSTOM_ATTR_BITS;
1245 for (i = 0; i < count; ++i) {
1246 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1247 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1248 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1249 type = mono_metadata_token_index (token);
1250 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1251 switch (mono_metadata_token_table (token)) {
1252 case MONO_TABLE_METHOD:
1253 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1255 case MONO_TABLE_MEMBERREF:
1256 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1259 g_warning ("got wrong token in custom attr");
1262 values [MONO_CUSTOM_ATTR_TYPE] = type;
1264 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1265 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1266 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1267 values += MONO_CUSTOM_ATTR_SIZE;
1273 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1275 MonoDynamicTable *table;
1277 guint32 count, i, idx;
1278 MonoReflectionPermissionSet *perm;
1283 count = mono_array_length (permissions);
1284 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1285 table->rows += count;
1286 alloc_table (table, table->rows);
1288 for (i = 0; i < mono_array_length (permissions); ++i) {
1289 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1291 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1293 idx = mono_metadata_token_index (parent_token);
1294 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1295 switch (mono_metadata_token_table (parent_token)) {
1296 case MONO_TABLE_TYPEDEF:
1297 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1299 case MONO_TABLE_METHOD:
1300 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1302 case MONO_TABLE_ASSEMBLY:
1303 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1306 g_assert_not_reached ();
1309 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1310 values [MONO_DECL_SECURITY_PARENT] = idx;
1311 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1318 * Fill in the MethodDef and ParamDef tables for a method.
1319 * This is used for both normal methods and constructors.
1322 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1324 MonoDynamicTable *table;
1328 /* room in this table is already allocated */
1329 table = &assembly->tables [MONO_TABLE_METHOD];
1330 *mb->table_idx = table->next_idx ++;
1331 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1332 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1333 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1334 values [MONO_METHOD_FLAGS] = mb->attrs;
1335 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1336 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1337 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1339 table = &assembly->tables [MONO_TABLE_PARAM];
1340 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1342 mono_image_add_decl_security (assembly,
1343 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1346 MonoDynamicTable *mtable;
1349 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1350 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1353 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1354 if (mono_array_get (mb->pinfo, gpointer, i))
1357 table->rows += count;
1358 alloc_table (table, table->rows);
1359 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1360 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1361 MonoReflectionParamBuilder *pb;
1362 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1363 values [MONO_PARAM_FLAGS] = pb->attrs;
1364 values [MONO_PARAM_SEQUENCE] = i;
1365 if (pb->name != NULL) {
1366 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1368 values [MONO_PARAM_NAME] = 0;
1370 values += MONO_PARAM_SIZE;
1371 if (pb->marshal_info) {
1373 alloc_table (mtable, mtable->rows);
1374 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1375 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1376 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1378 pb->table_idx = table->next_idx++;
1379 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1380 guint32 field_type = 0;
1381 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1383 alloc_table (mtable, mtable->rows);
1384 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1385 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1386 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1387 mvalues [MONO_CONSTANT_TYPE] = field_type;
1388 mvalues [MONO_CONSTANT_PADDING] = 0;
1396 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1398 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1400 rmb->ilgen = mb->ilgen;
1401 rmb->rtype = mb->rtype;
1402 rmb->parameters = mb->parameters;
1403 rmb->generic_params = mb->generic_params;
1404 rmb->generic_container = mb->generic_container;
1405 rmb->opt_types = NULL;
1406 rmb->pinfo = mb->pinfo;
1407 rmb->attrs = mb->attrs;
1408 rmb->iattrs = mb->iattrs;
1409 rmb->call_conv = mb->call_conv;
1410 rmb->code = mb->code;
1411 rmb->type = mb->type;
1412 rmb->name = mb->name;
1413 rmb->table_idx = &mb->table_idx;
1414 rmb->init_locals = mb->init_locals;
1415 rmb->skip_visibility = FALSE;
1416 rmb->return_modreq = mb->return_modreq;
1417 rmb->return_modopt = mb->return_modopt;
1418 rmb->param_modreq = mb->param_modreq;
1419 rmb->param_modopt = mb->param_modopt;
1420 rmb->permissions = mb->permissions;
1421 rmb->mhandle = mb->mhandle;
1426 rmb->charset = mb->charset;
1427 rmb->extra_flags = mb->extra_flags;
1428 rmb->native_cc = mb->native_cc;
1429 rmb->dllentry = mb->dllentry;
1435 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1437 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1439 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1441 rmb->ilgen = mb->ilgen;
1442 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1443 rmb->parameters = mb->parameters;
1444 rmb->generic_params = NULL;
1445 rmb->generic_container = NULL;
1446 rmb->opt_types = NULL;
1447 rmb->pinfo = mb->pinfo;
1448 rmb->attrs = mb->attrs;
1449 rmb->iattrs = mb->iattrs;
1450 rmb->call_conv = mb->call_conv;
1452 rmb->type = mb->type;
1453 rmb->name = mono_string_new (mono_domain_get (), name);
1454 rmb->table_idx = &mb->table_idx;
1455 rmb->init_locals = mb->init_locals;
1456 rmb->skip_visibility = FALSE;
1457 rmb->return_modreq = NULL;
1458 rmb->return_modopt = NULL;
1459 rmb->param_modreq = mb->param_modreq;
1460 rmb->param_modopt = mb->param_modopt;
1461 rmb->permissions = mb->permissions;
1462 rmb->mhandle = mb->mhandle;
1468 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1470 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1472 rmb->ilgen = mb->ilgen;
1473 rmb->rtype = mb->rtype;
1474 rmb->parameters = mb->parameters;
1475 rmb->generic_params = NULL;
1476 rmb->generic_container = NULL;
1477 rmb->opt_types = NULL;
1479 rmb->attrs = mb->attrs;
1481 rmb->call_conv = mb->call_conv;
1483 rmb->type = (MonoObject *) mb->owner;
1484 rmb->name = mb->name;
1485 rmb->table_idx = NULL;
1486 rmb->init_locals = mb->init_locals;
1487 rmb->skip_visibility = mb->skip_visibility;
1488 rmb->return_modreq = NULL;
1489 rmb->return_modopt = NULL;
1490 rmb->param_modreq = NULL;
1491 rmb->param_modopt = NULL;
1492 rmb->permissions = NULL;
1493 rmb->mhandle = mb->mhandle;
1499 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1501 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1502 MonoDynamicTable *table;
1506 if (!mb->override_method)
1509 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1511 alloc_table (table, table->rows);
1512 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1513 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1514 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1516 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1517 switch (mono_metadata_token_table (tok)) {
1518 case MONO_TABLE_MEMBERREF:
1519 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1521 case MONO_TABLE_METHOD:
1522 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1525 g_assert_not_reached ();
1527 values [MONO_METHODIMPL_DECLARATION] = tok;
1531 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1533 MonoDynamicTable *table;
1535 ReflectionMethodBuilder rmb;
1538 reflection_methodbuilder_from_method_builder (&rmb, mb);
1540 mono_image_basic_method (&rmb, assembly);
1541 mb->table_idx = *rmb.table_idx;
1543 if (mb->dll) { /* It's a P/Invoke method */
1545 /* map CharSet values to on-disk values */
1546 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1547 int extra_flags = mb->extra_flags;
1548 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1550 alloc_table (table, table->rows);
1551 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1553 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1554 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1556 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1558 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1559 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1560 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1561 table = &assembly->tables [MONO_TABLE_MODULEREF];
1563 alloc_table (table, table->rows);
1564 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1565 values [MONO_IMPLMAP_SCOPE] = table->rows;
1569 if (mb->generic_params) {
1570 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1571 table->rows += mono_array_length (mb->generic_params);
1572 alloc_table (table, table->rows);
1573 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1574 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1576 mono_image_get_generic_param_info (
1577 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1584 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1586 ReflectionMethodBuilder rmb;
1588 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1590 mono_image_basic_method (&rmb, assembly);
1591 mb->table_idx = *rmb.table_idx;
1595 type_get_fully_qualified_name (MonoType *type)
1597 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1601 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1605 klass = my_mono_class_from_mono_type (type);
1607 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1608 ta = klass->image->assembly;
1609 if (ta->dynamic || (ta == ass)) {
1610 if (klass->generic_class || klass->generic_container)
1611 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1612 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1614 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1617 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1621 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1626 if (!assembly->save)
1629 sigbuffer_init (&buf, 32);
1631 sigbuffer_add_value (&buf, 0x06);
1632 /* encode custom attributes before the type */
1633 /* FIXME: This should probably go in encode_type () */
1634 if (type->num_mods) {
1635 for (i = 0; i < type->num_mods; ++i) {
1636 if (type->modifiers [i].required)
1637 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1639 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1640 sigbuffer_add_value (&buf, type->modifiers [i].token);
1643 encode_type (assembly, type, &buf);
1644 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1645 sigbuffer_free (&buf);
1650 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1655 sigbuffer_init (&buf, 32);
1657 sigbuffer_add_value (&buf, 0x06);
1658 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1659 /* encode custom attributes before the type */
1660 encode_reflection_type (assembly, fb->type, &buf);
1661 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1662 sigbuffer_free (&buf);
1667 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1668 char blob_size [64];
1669 char *b = blob_size;
1672 guint32 idx = 0, len = 0, dummy = 0;
1674 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1675 guint32 fpa_double [2];
1680 p = buf = g_malloc (64);
1682 *ret_type = MONO_TYPE_CLASS;
1684 box_val = (char*)&dummy;
1686 box_val = ((char*)val) + sizeof (MonoObject);
1687 *ret_type = val->vtable->klass->byval_arg.type;
1690 switch (*ret_type) {
1691 case MONO_TYPE_BOOLEAN:
1696 case MONO_TYPE_CHAR:
1713 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1714 fpa_p = (guint32*)box_val;
1715 fpa_double [0] = fpa_p [1];
1716 fpa_double [1] = fpa_p [0];
1717 box_val = (char*)fpa_double;
1721 case MONO_TYPE_VALUETYPE:
1722 if (val->vtable->klass->enumtype) {
1723 *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1726 g_error ("we can't encode valuetypes");
1727 case MONO_TYPE_CLASS:
1729 case MONO_TYPE_STRING: {
1730 MonoString *str = (MonoString*)val;
1731 /* there is no signature */
1732 len = str->length * 2;
1733 mono_metadata_encode_value (len, b, &b);
1734 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1736 char *swapped = g_malloc (2 * mono_string_length (str));
1737 const char *p = (const char*)mono_string_chars (str);
1739 swap_with_size (swapped, p, 2, mono_string_length (str));
1740 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1744 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1750 case MONO_TYPE_GENERICINST:
1751 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1754 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1757 /* there is no signature */
1758 mono_metadata_encode_value (len, b, &b);
1759 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1760 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1761 swap_with_size (blob_size, box_val, len, 1);
1762 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1764 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1772 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1777 sigbuffer_init (&buf, 32);
1779 sigbuffer_add_value (&buf, minfo->type);
1781 switch (minfo->type) {
1782 case MONO_NATIVE_BYVALTSTR:
1783 case MONO_NATIVE_BYVALARRAY:
1784 sigbuffer_add_value (&buf, minfo->count);
1786 case MONO_NATIVE_LPARRAY:
1787 if (minfo->eltype || minfo->has_size) {
1788 sigbuffer_add_value (&buf, minfo->eltype);
1789 if (minfo->has_size) {
1790 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1791 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1793 /* LAMESPEC: ElemMult is undocumented */
1794 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1798 case MONO_NATIVE_CUSTOM:
1800 str = mono_string_to_utf8 (minfo->guid);
1802 sigbuffer_add_value (&buf, len);
1803 sigbuffer_add_mem (&buf, str, len);
1806 sigbuffer_add_value (&buf, 0);
1808 /* native type name */
1809 sigbuffer_add_value (&buf, 0);
1810 /* custom marshaler type name */
1811 if (minfo->marshaltype || minfo->marshaltyperef) {
1812 if (minfo->marshaltyperef)
1813 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1815 str = mono_string_to_utf8 (minfo->marshaltype);
1817 sigbuffer_add_value (&buf, len);
1818 sigbuffer_add_mem (&buf, str, len);
1821 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1822 sigbuffer_add_value (&buf, 0);
1824 if (minfo->mcookie) {
1825 str = mono_string_to_utf8 (minfo->mcookie);
1827 sigbuffer_add_value (&buf, len);
1828 sigbuffer_add_mem (&buf, str, len);
1831 sigbuffer_add_value (&buf, 0);
1837 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1838 sigbuffer_free (&buf);
1843 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1845 MonoDynamicTable *table;
1848 /* maybe this fixup should be done in the C# code */
1849 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1850 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1851 table = &assembly->tables [MONO_TABLE_FIELD];
1852 fb->table_idx = table->next_idx ++;
1853 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1854 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1855 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1856 values [MONO_FIELD_FLAGS] = fb->attrs;
1857 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1859 if (fb->offset != -1) {
1860 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1862 alloc_table (table, table->rows);
1863 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1864 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1865 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1867 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1868 guint32 field_type = 0;
1869 table = &assembly->tables [MONO_TABLE_CONSTANT];
1871 alloc_table (table, table->rows);
1872 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1873 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1874 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1875 values [MONO_CONSTANT_TYPE] = field_type;
1876 values [MONO_CONSTANT_PADDING] = 0;
1878 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1880 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1882 alloc_table (table, table->rows);
1883 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1884 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1886 * We store it in the code section because it's simpler for now.
1889 if (mono_array_length (fb->rva_data) >= 10)
1890 stream_data_align (&assembly->code);
1891 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1893 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1894 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1896 if (fb->marshal_info) {
1897 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1899 alloc_table (table, table->rows);
1900 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1901 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1902 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1907 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1910 guint32 nparams = 0;
1911 MonoReflectionMethodBuilder *mb = fb->get_method;
1912 MonoReflectionMethodBuilder *smb = fb->set_method;
1915 if (mb && mb->parameters)
1916 nparams = mono_array_length (mb->parameters);
1917 if (!mb && smb && smb->parameters)
1918 nparams = mono_array_length (smb->parameters) - 1;
1919 sigbuffer_init (&buf, 32);
1920 sigbuffer_add_byte (&buf, 0x08);
1921 sigbuffer_add_value (&buf, nparams);
1923 encode_reflection_type (assembly, mb->rtype, &buf);
1924 for (i = 0; i < nparams; ++i) {
1925 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1926 encode_reflection_type (assembly, pt, &buf);
1928 } else if (smb && smb->parameters) {
1929 /* the property type is the last param */
1930 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1931 for (i = 0; i < nparams; ++i) {
1932 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1933 encode_reflection_type (assembly, pt, &buf);
1936 encode_reflection_type (assembly, fb->type, &buf);
1939 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1940 sigbuffer_free (&buf);
1945 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1947 MonoDynamicTable *table;
1949 guint num_methods = 0;
1953 * we need to set things in the following tables:
1954 * PROPERTYMAP (info already filled in _get_type_info ())
1955 * PROPERTY (rows already preallocated in _get_type_info ())
1956 * METHOD (method info already done with the generic method code)
1959 table = &assembly->tables [MONO_TABLE_PROPERTY];
1960 pb->table_idx = table->next_idx ++;
1961 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1962 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1963 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1964 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1966 /* FIXME: we still don't handle 'other' methods */
1967 if (pb->get_method) num_methods ++;
1968 if (pb->set_method) num_methods ++;
1970 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1971 table->rows += num_methods;
1972 alloc_table (table, table->rows);
1974 if (pb->get_method) {
1975 semaidx = table->next_idx ++;
1976 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1977 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1978 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1979 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1981 if (pb->set_method) {
1982 semaidx = table->next_idx ++;
1983 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1984 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1985 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1986 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1991 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1993 MonoDynamicTable *table;
1995 guint num_methods = 0;
1999 * we need to set things in the following tables:
2000 * EVENTMAP (info already filled in _get_type_info ())
2001 * EVENT (rows already preallocated in _get_type_info ())
2002 * METHOD (method info already done with the generic method code)
2005 table = &assembly->tables [MONO_TABLE_EVENT];
2006 eb->table_idx = table->next_idx ++;
2007 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2008 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2009 values [MONO_EVENT_FLAGS] = eb->attrs;
2010 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
2013 * FIXME: we still don't handle 'other' methods
2015 if (eb->add_method) num_methods ++;
2016 if (eb->remove_method) num_methods ++;
2017 if (eb->raise_method) num_methods ++;
2019 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2020 table->rows += num_methods;
2021 alloc_table (table, table->rows);
2023 if (eb->add_method) {
2024 semaidx = table->next_idx ++;
2025 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2026 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2027 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2028 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2030 if (eb->remove_method) {
2031 semaidx = table->next_idx ++;
2032 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2033 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2034 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2035 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2037 if (eb->raise_method) {
2038 semaidx = table->next_idx ++;
2039 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2040 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2041 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2042 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2047 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2049 MonoDynamicTable *table;
2050 guint32 num_constraints, i;
2054 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2055 num_constraints = gparam->iface_constraints ?
2056 mono_array_length (gparam->iface_constraints) : 0;
2057 table->rows += num_constraints;
2058 if (gparam->base_type)
2060 alloc_table (table, table->rows);
2062 if (gparam->base_type) {
2063 table_idx = table->next_idx ++;
2064 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2066 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2067 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2068 assembly, gparam->base_type->type);
2071 for (i = 0; i < num_constraints; i++) {
2072 MonoReflectionType *constraint = mono_array_get (
2073 gparam->iface_constraints, gpointer, i);
2075 table_idx = table->next_idx ++;
2076 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2078 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2079 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2080 assembly, constraint->type);
2085 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2087 GenericParamTableEntry *entry;
2090 * The GenericParam table must be sorted according to the `owner' field.
2091 * We need to do this sorting prior to writing the GenericParamConstraint
2092 * table, since we have to use the final GenericParam table indices there
2093 * and they must also be sorted.
2096 entry = g_new0 (GenericParamTableEntry, 1);
2097 entry->owner = owner;
2098 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2099 MOVING_GC_REGISTER (&entry->gparam);
2100 entry->gparam = gparam;
2102 g_ptr_array_add (assembly->gen_params, entry);
2106 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2108 MonoDynamicTable *table;
2109 MonoGenericParam *param;
2113 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2114 table_idx = table->next_idx ++;
2115 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2117 param = entry->gparam->type.type->data.generic_param;
2119 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2120 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2121 values [MONO_GENERICPARAM_NUMBER] = param->num;
2122 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2124 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2126 encode_constraints (entry->gparam, table_idx, assembly);
2130 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2132 MonoDynamicTable *table;
2135 guint32 cols [MONO_ASSEMBLY_SIZE];
2139 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2142 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2143 table = &assembly->tables [MONO_TABLE_MODULEREF];
2144 token = table->next_idx ++;
2146 alloc_table (table, table->rows);
2147 values = table->values + token * MONO_MODULEREF_SIZE;
2148 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2150 token <<= MONO_RESOLTION_SCOPE_BITS;
2151 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2152 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2157 if (image->assembly->dynamic)
2159 memset (cols, 0, sizeof (cols));
2161 /* image->assembly->image is the manifest module */
2162 image = image->assembly->image;
2163 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2166 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2167 token = table->next_idx ++;
2169 alloc_table (table, table->rows);
2170 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2171 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2172 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2173 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2174 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2175 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2176 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2177 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2178 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2180 if (strcmp ("", image->assembly->aname.culture)) {
2181 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2182 image->assembly->aname.culture);
2185 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2186 guchar pubtoken [9];
2188 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2189 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2191 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2193 token <<= MONO_RESOLTION_SCOPE_BITS;
2194 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2195 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2200 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2202 MonoDynamicTable *table;
2207 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2210 sigbuffer_init (&buf, 32);
2211 switch (type->type) {
2212 case MONO_TYPE_FNPTR:
2214 case MONO_TYPE_SZARRAY:
2215 case MONO_TYPE_ARRAY:
2217 case MONO_TYPE_MVAR:
2218 case MONO_TYPE_GENERICINST:
2219 encode_type (assembly, type, &buf);
2221 case MONO_TYPE_CLASS:
2222 case MONO_TYPE_VALUETYPE: {
2223 MonoClass *k = mono_class_from_mono_type (type);
2224 if (!k || !k->generic_container) {
2225 sigbuffer_free (&buf);
2228 encode_type (assembly, type, &buf);
2232 sigbuffer_free (&buf);
2236 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2237 if (assembly->save) {
2238 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2239 alloc_table (table, table->rows + 1);
2240 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2241 values [MONO_TYPESPEC_SIGNATURE] = token;
2243 sigbuffer_free (&buf);
2245 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2246 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2252 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2254 MonoDynamicTable *table;
2256 guint32 token, scope, enclosing;
2259 /* if the type requires a typespec, we must try that first*/
2260 if (try_typespec && (token = create_typespec (assembly, type)))
2262 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2265 klass = my_mono_class_from_mono_type (type);
2267 klass = mono_class_from_mono_type (type);
2270 * If it's in the same module and not a generic type parameter:
2272 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2273 (type->type != MONO_TYPE_MVAR)) {
2274 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2275 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2276 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2280 if (klass->nested_in) {
2281 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2282 /* get the typeref idx of the enclosing type */
2283 enclosing >>= MONO_TYPEDEFORREF_BITS;
2284 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2286 scope = resolution_scope_from_image (assembly, klass->image);
2288 table = &assembly->tables [MONO_TABLE_TYPEREF];
2289 if (assembly->save) {
2290 alloc_table (table, table->rows + 1);
2291 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2292 values [MONO_TYPEREF_SCOPE] = scope;
2293 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2294 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2296 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2297 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2299 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2304 * Despite the name, we handle also TypeSpec (with the above helper).
2307 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2309 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2313 * Insert a memberef row into the metadata: the token that point to the memberref
2314 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2315 * mono_image_get_fieldref_token()).
2316 * The sig param is an index to an already built signature.
2319 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2321 MonoDynamicTable *table;
2323 guint32 token, pclass;
2326 parent = mono_image_typedef_or_ref (assembly, type);
2327 switch (parent & MONO_TYPEDEFORREF_MASK) {
2328 case MONO_TYPEDEFORREF_TYPEREF:
2329 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2331 case MONO_TYPEDEFORREF_TYPESPEC:
2332 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2334 case MONO_TYPEDEFORREF_TYPEDEF:
2335 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2338 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2341 /* extract the index */
2342 parent >>= MONO_TYPEDEFORREF_BITS;
2344 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2346 if (assembly->save) {
2347 alloc_table (table, table->rows + 1);
2348 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2349 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2350 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2351 values [MONO_MEMBERREF_SIGNATURE] = sig;
2354 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2361 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2364 MonoMethodSignature *sig;
2366 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2368 if (create_typespec) {
2369 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2374 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2375 if (token && !create_typespec)
2378 g_assert (!method->is_inflated);
2381 * A methodref signature can't contain an unmanaged calling convention.
2383 sig = mono_metadata_signature_dup (mono_method_signature (method));
2384 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2385 sig->call_convention = MONO_CALL_DEFAULT;
2386 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2387 method->name, method_encode_signature (assembly, sig));
2389 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2392 if (create_typespec) {
2393 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2394 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2395 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2397 if (assembly->save) {
2400 alloc_table (table, table->rows + 1);
2401 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2402 values [MONO_METHODSPEC_METHOD] = token;
2403 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2406 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2408 /*methodspec and memberef tokens are diferent, */
2409 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2416 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2419 ReflectionMethodBuilder rmb;
2422 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2426 name = mono_string_to_utf8 (method->name);
2427 reflection_methodbuilder_from_method_builder (&rmb, method);
2430 * A methodref signature can't contain an unmanaged calling convention.
2431 * Since some flags are encoded as part of call_conv, we need to check against it.
2433 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2434 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2435 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2436 name, method_builder_encode_signature (assembly, &rmb));
2439 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2444 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2445 const gchar *name, guint32 sig)
2447 MonoDynamicTable *table;
2451 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2453 if (assembly->save) {
2454 alloc_table (table, table->rows + 1);
2455 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2456 values [MONO_MEMBERREF_CLASS] = original;
2457 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2458 values [MONO_MEMBERREF_SIGNATURE] = sig;
2461 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2468 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2472 guint32 nparams = mono_array_length (mb->generic_params);
2475 if (!assembly->save)
2478 sigbuffer_init (&buf, 32);
2480 sigbuffer_add_value (&buf, 0xa);
2481 sigbuffer_add_value (&buf, nparams);
2483 for (i = 0; i < nparams; i++) {
2484 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2485 sigbuffer_add_value (&buf, i);
2488 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2489 sigbuffer_free (&buf);
2494 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2496 MonoDynamicTable *table;
2498 guint32 token, mtoken = 0;
2500 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2504 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2506 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2507 switch (mono_metadata_token_table (mtoken)) {
2508 case MONO_TABLE_MEMBERREF:
2509 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2511 case MONO_TABLE_METHOD:
2512 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2515 g_assert_not_reached ();
2518 if (assembly->save) {
2519 alloc_table (table, table->rows + 1);
2520 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2521 values [MONO_METHODSPEC_METHOD] = mtoken;
2522 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2525 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2528 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2533 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2537 if (mb->generic_params && create_methodspec)
2538 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2540 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2544 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2545 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2550 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2553 ReflectionMethodBuilder rmb;
2556 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2560 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2562 name = mono_string_to_utf8 (rmb.name);
2563 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2564 name, method_builder_encode_signature (assembly, &rmb));
2567 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2572 is_field_on_inst (MonoClassField *field)
2574 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2578 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2581 get_field_on_inst_generic_type (MonoClassField *field)
2583 MonoDynamicGenericClass *dgclass;
2586 g_assert (is_field_on_inst (field));
2588 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2589 field_index = field - dgclass->fields;
2591 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2592 return dgclass->field_generic_types [field_index];
2596 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2600 MonoClassField *field;
2602 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2605 g_assert (f->field->parent);
2608 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2609 int index = field - field->parent->fields;
2610 type = field->parent->generic_class->container_class->fields [index].type;
2612 if (is_field_on_inst (f->field))
2613 type = get_field_on_inst_generic_type (f->field);
2615 type = f->field->type;
2617 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2618 mono_field_get_name (f->field),
2619 fieldref_encode_signature (assembly, type));
2620 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2625 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2629 MonoGenericClass *gclass;
2630 MonoDynamicGenericClass *dgclass;
2631 MonoReflectionFieldBuilder *fb = f->fb;
2634 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2637 klass = mono_class_from_mono_type (f->inst->type.type);
2638 gclass = f->inst->type.type->data.generic_class;
2639 g_assert (gclass->is_dynamic);
2640 dgclass = (MonoDynamicGenericClass *) gclass;
2642 name = mono_string_to_utf8 (fb->name);
2643 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2644 field_encode_signature (assembly, fb));
2646 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2651 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2655 MonoGenericClass *gclass;
2656 MonoDynamicGenericClass *dgclass;
2657 MonoReflectionCtorBuilder *cb = c->cb;
2658 ReflectionMethodBuilder rmb;
2661 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2663 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2666 klass = mono_class_from_mono_type (c->inst->type.type);
2667 gclass = c->inst->type.type->data.generic_class;
2668 g_assert (gclass->is_dynamic);
2669 dgclass = (MonoDynamicGenericClass *) gclass;
2671 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2673 name = mono_string_to_utf8 (rmb.name);
2675 sig = method_builder_encode_signature (assembly, &rmb);
2677 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2680 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2685 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2689 MonoGenericClass *gclass;
2690 MonoReflectionMethodBuilder *mb = m->mb;
2691 ReflectionMethodBuilder rmb;
2694 if (create_methodspec && mb->generic_params)
2696 g_assert_not_reached ();
2698 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2701 klass = mono_class_from_mono_type (m->inst->type.type);
2702 gclass = m->inst->type.type->data.generic_class;
2703 g_assert (gclass->is_dynamic);
2705 reflection_methodbuilder_from_method_builder (&rmb, mb);
2707 name = mono_string_to_utf8 (rmb.name);
2709 sig = method_builder_encode_signature (assembly, &rmb);
2711 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2714 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2719 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2723 guint32 nparams = context->method_inst->type_argc;
2726 if (!assembly->save)
2729 sigbuffer_init (&buf, 32);
2731 * FIXME: vararg, explicit_this, differenc call_conv values...
2733 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2734 sigbuffer_add_value (&buf, nparams);
2736 for (i = 0; i < nparams; i++)
2737 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2739 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2740 sigbuffer_free (&buf);
2745 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2747 MonoDynamicTable *table;
2749 guint32 token, mtoken = 0, sig;
2750 MonoMethodInflated *imethod;
2751 MonoMethod *declaring;
2753 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2755 g_assert (method->is_inflated);
2756 imethod = (MonoMethodInflated *) method;
2757 declaring = imethod->declaring;
2759 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2760 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2762 if (!mono_method_signature (declaring)->generic_param_count)
2765 switch (mono_metadata_token_table (mtoken)) {
2766 case MONO_TABLE_MEMBERREF:
2767 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2769 case MONO_TABLE_METHOD:
2770 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2773 g_assert_not_reached ();
2776 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2778 if (assembly->save) {
2779 alloc_table (table, table->rows + 1);
2780 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2781 values [MONO_METHODSPEC_METHOD] = mtoken;
2782 values [MONO_METHODSPEC_SIGNATURE] = sig;
2785 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2792 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2794 MonoMethodInflated *imethod;
2797 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2801 g_assert (method->is_inflated);
2802 imethod = (MonoMethodInflated *) method;
2804 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2805 token = method_encode_methodspec (assembly, method);
2807 guint32 sig = method_encode_signature (
2808 assembly, mono_method_signature (imethod->declaring));
2809 token = mono_image_get_memberref_token (
2810 assembly, &method->klass->byval_arg, method->name, sig);
2813 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2818 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2820 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2823 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2824 token = mono_image_get_memberref_token (
2825 assembly, &m->klass->byval_arg, m->name, sig);
2831 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2833 MonoDynamicTable *table;
2841 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2842 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2843 * Because of this, we must not insert it into the `typeref' hash table.
2846 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2850 sigbuffer_init (&buf, 32);
2852 g_assert (tb->generic_params);
2853 klass = mono_class_from_mono_type (tb->type.type);
2855 if (tb->generic_container)
2856 mono_reflection_create_generic_class (tb);
2858 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2859 g_assert (klass->generic_container);
2860 sigbuffer_add_value (&buf, klass->byval_arg.type);
2861 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2863 count = mono_array_length (tb->generic_params);
2864 sigbuffer_add_value (&buf, count);
2865 for (i = 0; i < count; i++) {
2866 MonoReflectionGenericParam *gparam;
2868 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2870 encode_type (assembly, gparam->type.type, &buf);
2873 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2875 if (assembly->save) {
2876 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2877 alloc_table (table, table->rows + 1);
2878 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2879 values [MONO_TYPESPEC_SIGNATURE] = token;
2881 sigbuffer_free (&buf);
2883 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2884 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2890 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2893 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2895 int i, count, len, pos;
2900 count += mono_array_length (modreq);
2902 count += mono_array_length (modopt);
2905 return mono_metadata_type_dup (NULL, type);
2907 len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
2909 memcpy (t, type, len);
2911 t->num_mods = count;
2914 for (i = 0; i < mono_array_length (modreq); ++i) {
2915 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
2916 t->modifiers [pos].required = 1;
2917 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2922 for (i = 0; i < mono_array_length (modopt); ++i) {
2923 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
2924 t->modifiers [pos].required = 0;
2925 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2934 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2936 MonoDynamicTable *table;
2938 MonoType *custom = NULL;
2940 guint32 token, pclass, parent, sig;
2943 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2947 klass = mono_class_from_mono_type (fb->typeb->type);
2948 name = mono_string_to_utf8 (fb->name);
2950 /* fb->type does not include the custom modifiers */
2951 /* FIXME: We should do this in one place when a fieldbuilder is created */
2952 if (fb->modreq || fb->modopt) {
2953 custom = add_custom_modifiers (assembly, fb->type->type, fb->modreq, fb->modopt);
2954 sig = fieldref_encode_signature (assembly, custom);
2957 sig = fieldref_encode_signature (assembly, fb->type->type);
2960 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2961 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2963 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2964 parent >>= MONO_TYPEDEFORREF_BITS;
2966 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2968 if (assembly->save) {
2969 alloc_table (table, table->rows + 1);
2970 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2971 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2972 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2973 values [MONO_MEMBERREF_SIGNATURE] = sig;
2976 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2978 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2984 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2991 if (!assembly->save)
2994 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2995 g_assert (helper->type == 2);
2997 if (helper->arguments)
2998 nargs = mono_array_length (helper->arguments);
3002 size = 10 + (nargs * 10);
3004 sigbuffer_init (&buf, 32);
3006 /* Encode calling convention */
3007 /* Change Any to Standard */
3008 if ((helper->call_conv & 0x03) == 0x03)
3009 helper->call_conv = 0x01;
3010 /* explicit_this implies has_this */
3011 if (helper->call_conv & 0x40)
3012 helper->call_conv &= 0x20;
3014 if (helper->call_conv == 0) { /* Unmanaged */
3015 idx = helper->unmanaged_call_conv - 1;
3018 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3019 if (helper->call_conv & 0x02) /* varargs */
3023 sigbuffer_add_byte (&buf, idx);
3024 sigbuffer_add_value (&buf, nargs);
3025 encode_reflection_type (assembly, helper->return_type, &buf);
3026 for (i = 0; i < nargs; ++i) {
3027 MonoArray *modreqs = NULL;
3028 MonoArray *modopts = NULL;
3029 MonoReflectionType *pt;
3031 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3032 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3033 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3034 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3036 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3037 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3038 encode_reflection_type (assembly, pt, &buf);
3040 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3041 sigbuffer_free (&buf);
3047 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3050 MonoDynamicTable *table;
3053 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3054 idx = table->next_idx ++;
3056 alloc_table (table, table->rows);
3057 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3059 values [MONO_STAND_ALONE_SIGNATURE] =
3060 mono_reflection_encode_sighelper (assembly, helper);
3066 reflection_cc_to_file (int call_conv) {
3067 switch (call_conv & 0x3) {
3069 case 1: return MONO_CALL_DEFAULT;
3070 case 2: return MONO_CALL_VARARG;
3072 g_assert_not_reached ();
3079 MonoMethodSignature *sig;
3085 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3090 MonoMethodSignature *sig;
3093 name = mono_string_to_utf8 (m->name);
3094 nparams = mono_array_length (m->parameters);
3095 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
3097 sig->sentinelpos = -1;
3098 sig->call_convention = reflection_cc_to_file (m->call_conv);
3099 sig->param_count = nparams;
3100 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
3101 for (i = 0; i < nparams; ++i) {
3102 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
3103 sig->params [i] = t->type;
3106 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3108 if (strcmp (name, am->name) == 0 &&
3109 mono_metadata_type_equal (am->parent, m->parent->type) &&
3110 mono_metadata_signature_equal (am->sig, sig)) {
3113 m->table_idx = am->token & 0xffffff;
3117 am = g_new0 (ArrayMethod, 1);
3120 am->parent = m->parent->type;
3121 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3122 method_encode_signature (assembly, sig));
3123 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3124 m->table_idx = am->token & 0xffffff;
3129 * Insert into the metadata tables all the info about the TypeBuilder tb.
3130 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3133 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3135 MonoDynamicTable *table;
3137 int i, is_object = 0, is_system = 0;
3140 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3141 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3142 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3143 n = mono_string_to_utf8 (tb->name);
3144 if (strcmp (n, "Object") == 0)
3146 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3148 n = mono_string_to_utf8 (tb->nspace);
3149 if (strcmp (n, "System") == 0)
3151 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3153 if (tb->parent && !(is_system && is_object) &&
3154 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3155 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
3157 values [MONO_TYPEDEF_EXTENDS] = 0;
3159 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3160 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3163 * if we have explicitlayout or sequentiallayouts, output data in the
3164 * ClassLayout table.
3166 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3167 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3168 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3170 alloc_table (table, table->rows);
3171 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3172 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3173 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3174 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3177 /* handle interfaces */
3178 if (tb->interfaces) {
3179 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3181 table->rows += mono_array_length (tb->interfaces);
3182 alloc_table (table, table->rows);
3183 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3184 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3185 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3186 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3187 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3188 values += MONO_INTERFACEIMPL_SIZE;
3194 table = &assembly->tables [MONO_TABLE_FIELD];
3195 table->rows += tb->num_fields;
3196 alloc_table (table, table->rows);
3197 for (i = 0; i < tb->num_fields; ++i)
3198 mono_image_get_field_info (
3199 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3202 /* handle constructors */
3204 table = &assembly->tables [MONO_TABLE_METHOD];
3205 table->rows += mono_array_length (tb->ctors);
3206 alloc_table (table, table->rows);
3207 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3208 mono_image_get_ctor_info (domain,
3209 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3212 /* handle methods */
3214 table = &assembly->tables [MONO_TABLE_METHOD];
3215 table->rows += tb->num_methods;
3216 alloc_table (table, table->rows);
3217 for (i = 0; i < tb->num_methods; ++i)
3218 mono_image_get_method_info (
3219 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3222 /* Do the same with properties etc.. */
3223 if (tb->events && mono_array_length (tb->events)) {
3224 table = &assembly->tables [MONO_TABLE_EVENT];
3225 table->rows += mono_array_length (tb->events);
3226 alloc_table (table, table->rows);
3227 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3229 alloc_table (table, table->rows);
3230 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3231 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3232 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3233 for (i = 0; i < mono_array_length (tb->events); ++i)
3234 mono_image_get_event_info (
3235 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3237 if (tb->properties && mono_array_length (tb->properties)) {
3238 table = &assembly->tables [MONO_TABLE_PROPERTY];
3239 table->rows += mono_array_length (tb->properties);
3240 alloc_table (table, table->rows);
3241 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3243 alloc_table (table, table->rows);
3244 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3245 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3246 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3247 for (i = 0; i < mono_array_length (tb->properties); ++i)
3248 mono_image_get_property_info (
3249 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3252 /* handle generic parameters */
3253 if (tb->generic_params) {
3254 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3255 table->rows += mono_array_length (tb->generic_params);
3256 alloc_table (table, table->rows);
3257 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3258 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3260 mono_image_get_generic_param_info (
3261 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3265 mono_image_add_decl_security (assembly,
3266 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3269 MonoDynamicTable *ntable;
3271 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3272 ntable->rows += mono_array_length (tb->subtypes);
3273 alloc_table (ntable, ntable->rows);
3274 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3276 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3277 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3279 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3280 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3281 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3282 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3283 mono_string_to_utf8 (tb->name), tb->table_idx,
3284 ntable->next_idx, ntable->rows);*/
3285 values += MONO_NESTED_CLASS_SIZE;
3292 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3296 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3298 if (!type->subtypes)
3301 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3302 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3303 collect_types (types, subtype);
3308 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3310 if ((*type1)->table_idx < (*type2)->table_idx)
3313 if ((*type1)->table_idx > (*type2)->table_idx)
3320 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3325 for (i = 0; i < mono_array_length (pinfo); ++i) {
3326 MonoReflectionParamBuilder *pb;
3327 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3330 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3335 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3338 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3340 for (i = 0; i < tb->num_fields; ++i) {
3341 MonoReflectionFieldBuilder* fb;
3342 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3343 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3347 for (i = 0; i < mono_array_length (tb->events); ++i) {
3348 MonoReflectionEventBuilder* eb;
3349 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3350 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3353 if (tb->properties) {
3354 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3355 MonoReflectionPropertyBuilder* pb;
3356 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3357 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3361 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3362 MonoReflectionCtorBuilder* cb;
3363 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3364 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3365 params_add_cattrs (assembly, cb->pinfo);
3370 for (i = 0; i < tb->num_methods; ++i) {
3371 MonoReflectionMethodBuilder* mb;
3372 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3373 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3374 params_add_cattrs (assembly, mb->pinfo);
3379 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3380 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3385 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3389 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3391 if (moduleb->global_methods) {
3392 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3393 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3394 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3395 params_add_cattrs (assembly, mb->pinfo);
3399 if (moduleb->global_fields) {
3400 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3401 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3402 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3406 if (moduleb->types) {
3407 for (i = 0; i < moduleb->num_types; ++i)
3408 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3413 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3415 MonoDynamicTable *table;
3419 char *b = blob_size;
3422 table = &assembly->tables [MONO_TABLE_FILE];
3424 alloc_table (table, table->rows);
3425 values = table->values + table->next_idx * MONO_FILE_SIZE;
3426 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3427 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3428 if (module->image->dynamic) {
3429 /* This depends on the fact that the main module is emitted last */
3430 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3431 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3434 path = g_strdup (module->image->name);
3436 mono_sha1_get_digest_from_file (path, hash);
3439 mono_metadata_encode_value (20, b, &b);
3440 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3441 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3446 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3448 MonoDynamicTable *table;
3451 table = &assembly->tables [MONO_TABLE_MODULE];
3452 mb->table_idx = table->next_idx ++;
3453 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3454 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3457 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3458 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3459 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3460 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3464 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3465 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3467 MonoDynamicTable *table;
3471 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3472 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3475 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3477 alloc_table (table, table->rows);
3478 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3480 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3481 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3482 if (klass->nested_in)
3483 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3485 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3486 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3487 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3489 res = table->next_idx;
3493 /* Emit nested types */
3494 if (klass->ext && klass->ext->nested_classes) {
3497 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3498 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3505 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3506 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3511 klass = mono_class_from_mono_type (tb->type.type);
3513 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3515 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3516 parent_index, assembly);
3520 * We need to do this ourselves since klass->nested_classes is not set up.
3523 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3524 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3529 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3530 guint32 module_index, MonoDynamicImage *assembly)
3532 MonoImage *image = module->image;
3536 t = &image->tables [MONO_TABLE_TYPEDEF];
3538 for (i = 0; i < t->rows; ++i) {
3539 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3541 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3542 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3547 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3549 MonoDynamicTable *table;
3555 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3557 if (assemblyb->type_forwarders) {
3558 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3559 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3565 klass = mono_class_from_mono_type (t->type);
3567 scope = resolution_scope_from_image (assembly, klass->image);
3568 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3569 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3572 alloc_table (table, table->rows);
3573 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3575 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3576 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3577 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3578 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3579 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3586 #define align_pointer(base,p)\
3588 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3590 (p) += 4 - (__diff & 3);\
3594 compare_constants (const void *a, const void *b)
3596 const guint32 *a_values = a;
3597 const guint32 *b_values = b;
3598 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3602 compare_semantics (const void *a, const void *b)
3604 const guint32 *a_values = a;
3605 const guint32 *b_values = b;
3606 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3609 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3613 compare_custom_attrs (const void *a, const void *b)
3615 const guint32 *a_values = a;
3616 const guint32 *b_values = b;
3618 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3622 compare_field_marshal (const void *a, const void *b)
3624 const guint32 *a_values = a;
3625 const guint32 *b_values = b;
3627 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3631 compare_nested (const void *a, const void *b)
3633 const guint32 *a_values = a;
3634 const guint32 *b_values = b;
3636 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3640 compare_genericparam (const void *a, const void *b)
3642 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3643 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3645 if ((*b_entry)->owner == (*a_entry)->owner)
3647 (*a_entry)->gparam->type.type->data.generic_param->num -
3648 (*b_entry)->gparam->type.type->data.generic_param->num;
3650 return (*a_entry)->owner - (*b_entry)->owner;
3654 compare_declsecurity_attrs (const void *a, const void *b)
3656 const guint32 *a_values = a;
3657 const guint32 *b_values = b;
3659 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3663 compare_interface_impl (const void *a, const void *b)
3665 const guint32 *a_values = a;
3666 const guint32 *b_values = b;
3668 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3672 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3676 pad_heap (MonoDynamicStream *sh)
3678 if (sh->index & 3) {
3679 int sz = 4 - (sh->index & 3);
3680 memset (sh->data + sh->index, 0, sz);
3687 MonoDynamicStream *stream;
3691 * build_compressed_metadata() fills in the blob of data that represents the
3692 * raw metadata as it will be saved in the PE file. The five streams are output
3693 * and the metadata tables are comnpressed from the guint32 array representation,
3694 * to the compressed on-disk format.
3697 build_compressed_metadata (MonoDynamicImage *assembly)
3699 MonoDynamicTable *table;
3701 guint64 valid_mask = 0;
3702 guint64 sorted_mask;
3703 guint32 heapt_size = 0;
3704 guint32 meta_size = 256; /* allow for header and other stuff */
3705 guint32 table_offset;
3706 guint32 ntables = 0;
3712 struct StreamDesc stream_desc [5];
3714 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3715 for (i = 0; i < assembly->gen_params->len; i++){
3716 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3717 write_generic_param_entry (assembly, entry);
3720 stream_desc [0].name = "#~";
3721 stream_desc [0].stream = &assembly->tstream;
3722 stream_desc [1].name = "#Strings";
3723 stream_desc [1].stream = &assembly->sheap;
3724 stream_desc [2].name = "#US";
3725 stream_desc [2].stream = &assembly->us;
3726 stream_desc [3].name = "#Blob";
3727 stream_desc [3].stream = &assembly->blob;
3728 stream_desc [4].name = "#GUID";
3729 stream_desc [4].stream = &assembly->guid;
3731 /* tables that are sorted */
3732 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3733 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3734 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3735 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3736 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3737 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3738 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3740 /* Compute table sizes */
3741 /* the MonoImage has already been created in mono_image_basic_init() */
3742 meta = &assembly->image;
3744 /* sizes should be multiple of 4 */
3745 pad_heap (&assembly->blob);
3746 pad_heap (&assembly->guid);
3747 pad_heap (&assembly->sheap);
3748 pad_heap (&assembly->us);
3750 /* Setup the info used by compute_sizes () */
3751 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3752 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3753 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3755 meta_size += assembly->blob.index;
3756 meta_size += assembly->guid.index;
3757 meta_size += assembly->sheap.index;
3758 meta_size += assembly->us.index;
3760 for (i=0; i < MONO_TABLE_NUM; ++i)
3761 meta->tables [i].rows = assembly->tables [i].rows;
3763 for (i = 0; i < MONO_TABLE_NUM; i++){
3764 if (meta->tables [i].rows == 0)
3766 valid_mask |= (guint64)1 << i;
3768 meta->tables [i].row_size = mono_metadata_compute_size (
3769 meta, i, &meta->tables [i].size_bitfield);
3770 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3772 heapt_size += 24; /* #~ header size */
3773 heapt_size += ntables * 4;
3774 /* make multiple of 4 */
3777 meta_size += heapt_size;
3778 meta->raw_metadata = g_malloc0 (meta_size);
3779 p = (unsigned char*)meta->raw_metadata;
3780 /* the metadata signature */
3781 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3782 /* version numbers and 4 bytes reserved */
3783 int16val = (guint16*)p;
3784 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3785 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3787 /* version string */
3788 int32val = (guint32*)p;
3789 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3791 memcpy (p, meta->version, strlen (meta->version));
3792 p += GUINT32_FROM_LE (*int32val);
3793 align_pointer (meta->raw_metadata, p);
3794 int16val = (guint16*)p;
3795 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3796 *int16val = GUINT16_TO_LE (5); /* number of streams */
3800 * write the stream info.
3802 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3803 table_offset += 3; table_offset &= ~3;
3805 assembly->tstream.index = heapt_size;
3806 for (i = 0; i < 5; ++i) {
3807 int32val = (guint32*)p;
3808 stream_desc [i].stream->offset = table_offset;
3809 *int32val++ = GUINT32_TO_LE (table_offset);
3810 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3811 table_offset += GUINT32_FROM_LE (*int32val);
3812 table_offset += 3; table_offset &= ~3;
3814 strcpy ((char*)p, stream_desc [i].name);
3815 p += strlen (stream_desc [i].name) + 1;
3816 align_pointer (meta->raw_metadata, p);
3819 * now copy the data, the table stream header and contents goes first.
3821 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3822 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3823 int32val = (guint32*)p;
3824 *int32val = GUINT32_TO_LE (0); /* reserved */
3827 if (mono_framework_version () > 1) {
3828 *p++ = 2; /* version */
3831 *p++ = 1; /* version */
3835 if (meta->idx_string_wide)
3837 if (meta->idx_guid_wide)
3839 if (meta->idx_blob_wide)
3842 *p++ = 1; /* reserved */
3843 int64val = (guint64*)p;
3844 *int64val++ = GUINT64_TO_LE (valid_mask);
3845 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3847 int32val = (guint32*)p;
3848 for (i = 0; i < MONO_TABLE_NUM; i++){
3849 if (meta->tables [i].rows == 0)
3851 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3853 p = (unsigned char*)int32val;
3855 /* sort the tables that still need sorting */
3856 table = &assembly->tables [MONO_TABLE_CONSTANT];
3858 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3859 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3861 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3862 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3864 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3865 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3867 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3868 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3870 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3871 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3872 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3874 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3875 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3877 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3879 /* compress the tables */
3880 for (i = 0; i < MONO_TABLE_NUM; i++){
3883 guint32 bitfield = meta->tables [i].size_bitfield;
3884 if (!meta->tables [i].rows)
3886 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3887 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3888 meta->tables [i].base = (char*)p;
3889 for (row = 1; row <= meta->tables [i].rows; ++row) {
3890 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3891 for (col = 0; col < assembly->tables [i].columns; ++col) {
3892 switch (mono_metadata_table_size (bitfield, col)) {
3894 *p++ = values [col];
3897 *p++ = values [col] & 0xff;
3898 *p++ = (values [col] >> 8) & 0xff;
3901 *p++ = values [col] & 0xff;
3902 *p++ = (values [col] >> 8) & 0xff;
3903 *p++ = (values [col] >> 16) & 0xff;
3904 *p++ = (values [col] >> 24) & 0xff;
3907 g_assert_not_reached ();
3911 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3914 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3915 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3916 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3917 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3918 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3920 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3924 * Some tables in metadata need to be sorted according to some criteria, but
3925 * when methods and fields are first created with reflection, they may be assigned a token
3926 * that doesn't correspond to the final token they will get assigned after the sorting.
3927 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3928 * with the reflection objects that represent them. Once all the tables are set up, the
3929 * reflection objects will contains the correct table index. fixup_method() will fixup the
3930 * tokens for the method with ILGenerator @ilgen.
3933 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3935 guint32 code_idx = GPOINTER_TO_UINT (value);
3936 MonoReflectionILTokenInfo *iltoken;
3937 MonoReflectionFieldBuilder *field;
3938 MonoReflectionCtorBuilder *ctor;
3939 MonoReflectionMethodBuilder *method;
3940 MonoReflectionTypeBuilder *tb;
3941 MonoReflectionArrayMethod *am;
3943 unsigned char *target;
3945 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3946 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3947 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3948 switch (target [3]) {
3949 case MONO_TABLE_FIELD:
3950 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3951 field = (MonoReflectionFieldBuilder *)iltoken->member;
3952 idx = field->table_idx;
3953 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3954 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3955 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3957 g_assert_not_reached ();
3960 case MONO_TABLE_METHOD:
3961 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3962 method = (MonoReflectionMethodBuilder *)iltoken->member;
3963 idx = method->table_idx;
3964 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3965 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3966 idx = ctor->table_idx;
3967 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3968 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3969 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3970 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3972 g_assert_not_reached ();
3975 case MONO_TABLE_TYPEDEF:
3976 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3977 g_assert_not_reached ();
3978 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3979 idx = tb->table_idx;
3981 case MONO_TABLE_MEMBERREF:
3982 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3983 am = (MonoReflectionArrayMethod*)iltoken->member;
3984 idx = am->table_idx;
3985 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3986 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3987 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3988 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3989 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3990 g_assert (m->klass->generic_class || m->klass->generic_container);
3992 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3994 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3995 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3996 g_assert (is_field_on_inst (f));
3998 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3999 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4001 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4003 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4005 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4008 g_assert_not_reached ();
4011 case MONO_TABLE_METHODSPEC:
4012 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4013 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4014 g_assert (mono_method_signature (m)->generic_param_count);
4016 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4019 g_assert_not_reached ();
4023 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4025 target [0] = idx & 0xff;
4026 target [1] = (idx >> 8) & 0xff;
4027 target [2] = (idx >> 16) & 0xff;
4034 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4035 * value is not known when the table is emitted.
4038 fixup_cattrs (MonoDynamicImage *assembly)
4040 MonoDynamicTable *table;
4042 guint32 type, i, idx, token;
4045 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4047 for (i = 0; i < table->rows; ++i) {
4048 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4050 type = values [MONO_CUSTOM_ATTR_TYPE];
4051 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4052 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4053 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4054 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4057 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4058 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4059 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4060 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4067 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4069 MonoDynamicTable *table;
4072 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4074 alloc_table (table, table->rows);
4075 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4076 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4077 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4078 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4079 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4084 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4086 MonoDynamicTable *table;
4090 char *b = blob_size;
4092 guint32 idx, offset;
4094 if (rsrc->filename) {
4095 name = mono_string_to_utf8 (rsrc->filename);
4096 sname = g_path_get_basename (name);
4098 table = &assembly->tables [MONO_TABLE_FILE];
4100 alloc_table (table, table->rows);
4101 values = table->values + table->next_idx * MONO_FILE_SIZE;
4102 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4103 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4106 mono_sha1_get_digest_from_file (name, hash);
4107 mono_metadata_encode_value (20, b, &b);
4108 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4109 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4111 idx = table->next_idx++;
4113 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4119 data = mono_array_addr (rsrc->data, char, 0);
4120 len = mono_array_length (rsrc->data);
4126 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4127 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4128 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4129 mono_image_add_stream_data (&assembly->resources, data, len);
4133 * The entry should be emitted into the MANIFESTRESOURCE table of
4134 * the main module, but that needs to reference the FILE table
4135 * which isn't emitted yet.
4142 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4146 set_version_from_string (MonoString *version, guint32 *values)
4148 gchar *ver, *p, *str;
4151 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4152 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4153 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4154 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4157 ver = str = mono_string_to_utf8 (version);
4158 for (i = 0; i < 4; ++i) {
4159 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4165 /* handle Revision and Build */
4175 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4179 char *b = blob_size;
4184 len = mono_array_length (pkey);
4185 mono_metadata_encode_value (len, b, &b);
4186 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4187 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4189 assembly->public_key = g_malloc (len);
4190 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4191 assembly->public_key_len = len;
4193 /* Special case: check for ECMA key (16 bytes) */
4194 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4195 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4196 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4197 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4198 /* minimum key size (in 2.0) is 384 bits */
4199 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4201 /* FIXME - verifier */
4202 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4203 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4205 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4211 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4213 MonoDynamicTable *table;
4214 MonoDynamicImage *assembly;
4215 MonoReflectionAssemblyBuilder *assemblyb;
4219 guint32 module_index;
4221 assemblyb = moduleb->assemblyb;
4222 assembly = moduleb->dynamic_image;
4223 domain = mono_object_domain (assemblyb);
4225 /* Emit ASSEMBLY table */
4226 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4227 alloc_table (table, 1);
4228 values = table->values + MONO_ASSEMBLY_SIZE;
4229 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4230 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4231 if (assemblyb->culture) {
4232 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4234 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4236 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4237 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4238 set_version_from_string (assemblyb->version, values);
4240 /* Emit FILE + EXPORTED_TYPE table */
4242 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4244 MonoReflectionModuleBuilder *file_module =
4245 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4246 if (file_module != moduleb) {
4247 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4249 if (file_module->types) {
4250 for (j = 0; j < file_module->num_types; ++j) {
4251 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4252 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4257 if (assemblyb->loaded_modules) {
4258 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4259 MonoReflectionModule *file_module =
4260 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4261 mono_image_fill_file_table (domain, file_module, assembly);
4263 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4266 if (assemblyb->type_forwarders)
4267 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4269 /* Emit MANIFESTRESOURCE table */
4271 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4273 MonoReflectionModuleBuilder *file_module =
4274 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4275 /* The table for the main module is emitted later */
4276 if (file_module != moduleb) {
4278 if (file_module->resources) {
4279 int len = mono_array_length (file_module->resources);
4280 for (j = 0; j < len; ++j) {
4281 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4282 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4289 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4292 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4293 * for the modulebuilder @moduleb.
4294 * At the end of the process, method and field tokens are fixed up and the
4295 * on-disk compressed metadata representation is created.
4298 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4300 MonoDynamicTable *table;
4301 MonoDynamicImage *assembly;
4302 MonoReflectionAssemblyBuilder *assemblyb;
4308 assemblyb = moduleb->assemblyb;
4309 assembly = moduleb->dynamic_image;
4310 domain = mono_object_domain (assemblyb);
4312 if (assembly->text_rva)
4315 assembly->text_rva = START_TEXT_RVA;
4317 if (moduleb->is_main) {
4318 mono_image_emit_manifest (moduleb);
4321 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4322 table->rows = 1; /* .<Module> */
4324 alloc_table (table, table->rows);
4326 * Set the first entry.
4328 values = table->values + table->columns;
4329 values [MONO_TYPEDEF_FLAGS] = 0;
4330 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4331 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4332 values [MONO_TYPEDEF_EXTENDS] = 0;
4333 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4334 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4337 * handle global methods
4338 * FIXME: test what to do when global methods are defined in multiple modules.
4340 if (moduleb->global_methods) {
4341 table = &assembly->tables [MONO_TABLE_METHOD];
4342 table->rows += mono_array_length (moduleb->global_methods);
4343 alloc_table (table, table->rows);
4344 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4345 mono_image_get_method_info (
4346 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4348 if (moduleb->global_fields) {
4349 table = &assembly->tables [MONO_TABLE_FIELD];
4350 table->rows += mono_array_length (moduleb->global_fields);
4351 alloc_table (table, table->rows);
4352 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4353 mono_image_get_field_info (
4354 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4357 table = &assembly->tables [MONO_TABLE_MODULE];
4358 alloc_table (table, 1);
4359 mono_image_fill_module_table (domain, moduleb, assembly);
4361 /* Collect all types into a list sorted by their table_idx */
4362 types = g_ptr_array_new ();
4365 for (i = 0; i < moduleb->num_types; ++i) {
4366 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4367 collect_types (types, type);
4370 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4371 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4372 table->rows += types->len;
4373 alloc_table (table, table->rows);
4376 * Emit type names + namespaces at one place inside the string heap,
4377 * so load_class_names () needs to touch fewer pages.
4379 for (i = 0; i < types->len; ++i) {
4380 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4381 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4383 for (i = 0; i < types->len; ++i) {
4384 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4385 string_heap_insert_mstring (&assembly->sheap, tb->name);
4388 for (i = 0; i < types->len; ++i) {
4389 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4390 mono_image_get_type_info (domain, type, assembly);
4394 * table->rows is already set above and in mono_image_fill_module_table.
4396 /* add all the custom attributes at the end, once all the indexes are stable */
4397 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4399 /* CAS assembly permissions */
4400 if (assemblyb->permissions_minimum)
4401 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4402 if (assemblyb->permissions_optional)
4403 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4404 if (assemblyb->permissions_refused)
4405 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4407 module_add_cattrs (assembly, moduleb);
4410 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4412 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4413 * the final tokens and don't need another fixup pass. */
4415 if (moduleb->global_methods) {
4416 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4417 MonoReflectionMethodBuilder *mb = mono_array_get (
4418 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4419 mono_image_add_methodimpl (assembly, mb);
4423 for (i = 0; i < types->len; ++i) {
4424 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4425 if (type->methods) {
4426 for (j = 0; j < type->num_methods; ++j) {
4427 MonoReflectionMethodBuilder *mb = mono_array_get (
4428 type->methods, MonoReflectionMethodBuilder*, j);
4430 mono_image_add_methodimpl (assembly, mb);
4435 g_ptr_array_free (types, TRUE);
4437 fixup_cattrs (assembly);
4440 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4443 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4445 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4448 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4450 #ifndef DISABLE_REFLECTION_EMIT
4453 * mono_image_insert_string:
4454 * @module: module builder object
4457 * Insert @str into the user string stream of @module.
4460 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4462 MonoDynamicImage *assembly;
4467 MONO_ARCH_SAVE_REGS;
4469 if (!module->dynamic_image)
4470 mono_image_module_basic_init (module);
4472 assembly = module->dynamic_image;
4474 if (assembly->save) {
4475 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4476 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4477 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4479 char *swapped = g_malloc (2 * mono_string_length (str));
4480 const char *p = (const char*)mono_string_chars (str);
4482 swap_with_size (swapped, p, 2, mono_string_length (str));
4483 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4487 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4489 mono_image_add_stream_data (&assembly->us, "", 1);
4491 idx = assembly->us.index ++;
4494 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4496 return MONO_TOKEN_STRING | idx;
4500 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4505 klass = obj->vtable->klass;
4506 if (strcmp (klass->name, "MonoMethod") == 0) {
4507 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4508 MonoMethodSignature *sig, *old;
4509 guint32 sig_token, parent;
4512 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4514 nargs = mono_array_length (opt_param_types);
4515 old = mono_method_signature (method);
4516 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4518 sig->hasthis = old->hasthis;
4519 sig->explicit_this = old->explicit_this;
4520 sig->call_convention = old->call_convention;
4521 sig->generic_param_count = old->generic_param_count;
4522 sig->param_count = old->param_count + nargs;
4523 sig->sentinelpos = old->param_count;
4524 sig->ret = old->ret;
4526 for (i = 0; i < old->param_count; i++)
4527 sig->params [i] = old->params [i];
4529 for (i = 0; i < nargs; i++) {
4530 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4531 sig->params [old->param_count + i] = rt->type;
4534 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4535 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4536 parent >>= MONO_TYPEDEFORREF_BITS;
4538 parent <<= MONO_MEMBERREF_PARENT_BITS;
4539 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4541 sig_token = method_encode_signature (assembly, sig);
4542 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4543 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4544 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4545 ReflectionMethodBuilder rmb;
4546 guint32 parent, sig;
4549 reflection_methodbuilder_from_method_builder (&rmb, mb);
4550 rmb.opt_types = opt_param_types;
4552 sig = method_builder_encode_signature (assembly, &rmb);
4554 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4555 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4557 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4558 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4560 name = mono_string_to_utf8 (rmb.name);
4561 token = mono_image_get_varargs_method_token (
4562 assembly, parent, name, sig);
4565 g_error ("requested method token for %s\n", klass->name);
4572 * mono_image_create_token:
4573 * @assembly: a dynamic assembly
4575 * @register_token: Whenever to register the token in the assembly->tokens hash.
4577 * Get a token to insert in the IL code stream for the given MemberInfo.
4578 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4579 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4583 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4584 gboolean create_methodspec, gboolean register_token)
4589 klass = obj->vtable->klass;
4590 if (strcmp (klass->name, "MethodBuilder") == 0) {
4591 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4592 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4594 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4595 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4597 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4598 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4599 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4600 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4601 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4603 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4604 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4606 token = mono_image_get_ctorbuilder_token (assembly, mb);
4607 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4608 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4609 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4610 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4611 if (tb->generic_params) {
4612 token = mono_image_get_generic_field_token (assembly, fb);
4614 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4616 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4617 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4618 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4619 } else if (strcmp (klass->name, "MonoType") == 0) {
4620 MonoReflectionType *tb = (MonoReflectionType *)obj;
4621 MonoClass *mc = mono_class_from_mono_type (tb->type);
4622 token = mono_metadata_token_from_dor (
4623 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4624 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4625 MonoReflectionType *tb = (MonoReflectionType *)obj;
4626 token = mono_metadata_token_from_dor (
4627 mono_image_typedef_or_ref (assembly, tb->type));
4628 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4629 MonoReflectionType *tb = (MonoReflectionType *)obj;
4630 token = mono_metadata_token_from_dor (
4631 mono_image_typedef_or_ref (assembly, tb->type));
4632 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4633 strcmp (klass->name, "MonoMethod") == 0 ||
4634 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4635 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4636 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4637 if (m->method->is_inflated) {
4638 if (create_methodspec)
4639 token = mono_image_get_methodspec_token (assembly, m->method);
4641 token = mono_image_get_inflated_method_token (assembly, m->method);
4642 } else if ((m->method->klass->image == &assembly->image) &&
4643 !m->method->klass->generic_class) {
4644 static guint32 method_table_idx = 0xffffff;
4645 if (m->method->klass->wastypebuilder) {
4646 /* we use the same token as the one that was assigned
4647 * to the Methodbuilder.
4648 * FIXME: do the equivalent for Fields.
4650 token = m->method->token;
4653 * Each token should have a unique index, but the indexes are
4654 * assigned by managed code, so we don't know about them. An
4655 * easy solution is to count backwards...
4657 method_table_idx --;
4658 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4661 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4663 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4664 } else if (strcmp (klass->name, "MonoField") == 0) {
4665 MonoReflectionField *f = (MonoReflectionField *)obj;
4666 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4667 static guint32 field_table_idx = 0xffffff;
4669 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4671 token = mono_image_get_fieldref_token (assembly, f);
4673 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4674 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4675 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4676 token = mono_image_get_array_token (assembly, m);
4677 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4678 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4679 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4680 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4681 MonoReflectionType *tb = (MonoReflectionType *)obj;
4682 token = mono_metadata_token_from_dor (
4683 mono_image_typedef_or_ref (assembly, tb->type));
4684 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4685 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4686 token = mono_image_get_field_on_inst_token (assembly, f);
4687 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4688 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4689 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4690 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4691 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4692 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4694 g_error ("requested token for %s\n", klass->name);
4698 mono_image_register_token (assembly, token, obj);
4704 * mono_image_register_token:
4706 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4707 * the Module.ResolveXXXToken () methods to work.
4710 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4712 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4714 /* There could be multiple MethodInfo objects with the same token */
4715 //g_assert (prev == obj);
4717 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4721 #endif /* DISABLE_REFLECTION_EMIT */
4724 guint32 import_lookup_table;
4728 guint32 import_address_table_rva;
4736 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4738 static MonoDynamicImage*
4739 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4741 static const guchar entrycode [16] = {0xff, 0x25, 0};
4742 MonoDynamicImage *image;
4745 const char *version;
4747 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4748 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4750 version = mono_get_runtime_info ()->runtime_version;
4753 image = GC_MALLOC (sizeof (MonoDynamicImage));
4755 image = g_new0 (MonoDynamicImage, 1);
4758 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4760 /*g_print ("created image %p\n", image);*/
4761 /* keep in sync with image.c */
4762 image->image.name = assembly_name;
4763 image->image.assembly_name = image->image.name; /* they may be different */
4764 image->image.module_name = module_name;
4765 image->image.version = g_strdup (version);
4766 image->image.md_version_major = 1;
4767 image->image.md_version_minor = 1;
4768 image->image.dynamic = TRUE;
4770 image->image.references = g_new0 (MonoAssembly*, 1);
4771 image->image.references [0] = NULL;
4773 mono_image_init (&image->image);
4775 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4776 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4777 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4778 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4779 image->handleref = g_hash_table_new (NULL, NULL);
4780 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4781 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4782 image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4783 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4784 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4785 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4786 image->gen_params = g_ptr_array_new ();
4788 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4789 string_heap_init (&image->sheap);
4790 mono_image_add_stream_data (&image->us, "", 1);
4791 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4792 /* import tables... */
4793 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4794 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4795 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4796 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4797 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4798 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4799 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4800 stream_data_align (&image->code);
4802 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4804 for (i=0; i < MONO_TABLE_NUM; ++i) {
4805 image->tables [i].next_idx = 1;
4806 image->tables [i].columns = table_sizes [i];
4809 image->image.assembly = (MonoAssembly*)assembly;
4810 image->run = assembly->run;
4811 image->save = assembly->save;
4812 image->pe_kind = 0x1; /* ILOnly */
4813 image->machine = 0x14c; /* I386 */
4815 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4821 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4827 mono_dynamic_image_free (MonoDynamicImage *image)
4829 MonoDynamicImage *di = image;
4834 mono_g_hash_table_destroy (di->methodspec);
4836 g_hash_table_destroy (di->typespec);
4838 g_hash_table_destroy (di->typeref);
4840 g_hash_table_destroy (di->handleref);
4842 mono_g_hash_table_destroy (di->tokens);
4843 if (di->generic_def_objects)
4844 mono_g_hash_table_destroy (di->generic_def_objects);
4845 if (di->blob_cache) {
4846 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4847 g_hash_table_destroy (di->blob_cache);
4849 if (di->standalonesig_cache)
4850 g_hash_table_destroy (di->standalonesig_cache);
4851 for (list = di->array_methods; list; list = list->next) {
4852 ArrayMethod *am = (ArrayMethod *)list->data;
4857 g_list_free (di->array_methods);
4858 if (di->gen_params) {
4859 for (i = 0; i < di->gen_params->len; i++) {
4860 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4861 if (entry->gparam->type.type) {
4862 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4863 g_free ((char*)param->name);
4868 g_ptr_array_free (di->gen_params, TRUE);
4870 if (di->token_fixups)
4871 mono_g_hash_table_destroy (di->token_fixups);
4872 if (di->method_to_table_idx)
4873 g_hash_table_destroy (di->method_to_table_idx);
4874 if (di->field_to_table_idx)
4875 g_hash_table_destroy (di->field_to_table_idx);
4876 if (di->method_aux_hash)
4877 g_hash_table_destroy (di->method_aux_hash);
4878 g_free (di->strong_name);
4879 g_free (di->win32_res);
4881 g_free (di->public_key);
4883 /*g_print ("string heap destroy for image %p\n", di);*/
4884 mono_dynamic_stream_reset (&di->sheap);
4885 mono_dynamic_stream_reset (&di->code);
4886 mono_dynamic_stream_reset (&di->resources);
4887 mono_dynamic_stream_reset (&di->us);
4888 mono_dynamic_stream_reset (&di->blob);
4889 mono_dynamic_stream_reset (&di->tstream);
4890 mono_dynamic_stream_reset (&di->guid);
4891 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4892 g_free (di->tables [i].values);
4896 #ifndef DISABLE_REFLECTION_EMIT
4899 * mono_image_basic_init:
4900 * @assembly: an assembly builder object
4902 * Create the MonoImage that represents the assembly builder and setup some
4903 * of the helper hash table and the basic metadata streams.
4906 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4908 MonoDynamicAssembly *assembly;
4909 MonoDynamicImage *image;
4910 MonoDomain *domain = mono_object_domain (assemblyb);
4912 MONO_ARCH_SAVE_REGS;
4914 if (assemblyb->dynamic_assembly)
4918 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4920 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4923 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4925 assembly->assembly.ref_count = 1;
4926 assembly->assembly.dynamic = TRUE;
4927 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4928 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4929 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4930 if (assemblyb->culture)
4931 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4933 assembly->assembly.aname.culture = g_strdup ("");
4935 if (assemblyb->version) {
4936 char *vstr = mono_string_to_utf8 (assemblyb->version);
4937 char **version = g_strsplit (vstr, ".", 4);
4938 char **parts = version;
4939 assembly->assembly.aname.major = atoi (*parts++);
4940 assembly->assembly.aname.minor = atoi (*parts++);
4941 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4942 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4944 g_strfreev (version);
4947 assembly->assembly.aname.major = 0;
4948 assembly->assembly.aname.minor = 0;
4949 assembly->assembly.aname.build = 0;
4950 assembly->assembly.aname.revision = 0;
4953 assembly->run = assemblyb->access != 2;
4954 assembly->save = assemblyb->access != 1;
4956 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4957 image->initial_image = TRUE;
4958 assembly->assembly.aname.name = image->image.name;
4959 assembly->assembly.image = &image->image;
4961 mono_domain_assemblies_lock (domain);
4962 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4963 mono_domain_assemblies_unlock (domain);
4965 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4967 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4969 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4972 #endif /* DISABLE_REFLECTION_EMIT */
4975 calc_section_size (MonoDynamicImage *assembly)
4979 /* alignment constraints */
4980 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4981 g_assert ((assembly->code.index % 4) == 0);
4982 assembly->meta_size += 3;
4983 assembly->meta_size &= ~3;
4984 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4985 g_assert ((assembly->resources.index % 4) == 0);
4987 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4988 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4991 if (assembly->win32_res) {
4992 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4994 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4995 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4999 assembly->sections [MONO_SECTION_RELOC].size = 12;
5000 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5010 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5014 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5016 ResTreeNode *t1 = (ResTreeNode*)a;
5017 ResTreeNode *t2 = (ResTreeNode*)b;
5019 return t1->id - t2->id;
5023 * resource_tree_create:
5025 * Organize the resources into a resource tree.
5027 static ResTreeNode *
5028 resource_tree_create (MonoArray *win32_resources)
5030 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5034 tree = g_new0 (ResTreeNode, 1);
5036 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5037 MonoReflectionWin32Resource *win32_res =
5038 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5042 /* FIXME: BUG: this stores managed references in unmanaged memory */
5043 lang_node = g_new0 (ResTreeNode, 1);
5044 lang_node->id = win32_res->lang_id;
5045 lang_node->win32_res = win32_res;
5047 /* Create type node if neccesary */
5049 for (l = tree->children; l; l = l->next)
5050 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5051 type_node = (ResTreeNode*)l->data;
5056 type_node = g_new0 (ResTreeNode, 1);
5057 type_node->id = win32_res->res_type;
5060 * The resource types have to be sorted otherwise
5061 * Windows Explorer can't display the version information.
5063 tree->children = g_slist_insert_sorted (tree->children,
5064 type_node, resource_tree_compare_by_id);
5067 /* Create res node if neccesary */
5069 for (l = type_node->children; l; l = l->next)
5070 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5071 res_node = (ResTreeNode*)l->data;
5076 res_node = g_new0 (ResTreeNode, 1);
5077 res_node->id = win32_res->res_id;
5078 type_node->children = g_slist_append (type_node->children, res_node);
5081 res_node->children = g_slist_append (res_node->children, lang_node);
5088 * resource_tree_encode:
5090 * Encode the resource tree into the format used in the PE file.
5093 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5096 MonoPEResourceDir dir;
5097 MonoPEResourceDirEntry dir_entry;
5098 MonoPEResourceDataEntry data_entry;
5100 guint32 res_id_entries;
5103 * For the format of the resource directory, see the article
5104 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5108 memset (&dir, 0, sizeof (dir));
5109 memset (&dir_entry, 0, sizeof (dir_entry));
5110 memset (&data_entry, 0, sizeof (data_entry));
5112 g_assert (sizeof (dir) == 16);
5113 g_assert (sizeof (dir_entry) == 8);
5114 g_assert (sizeof (data_entry) == 16);
5116 node->offset = p - begin;
5118 /* IMAGE_RESOURCE_DIRECTORY */
5119 res_id_entries = g_slist_length (node->children);
5120 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5122 memcpy (p, &dir, sizeof (dir));
5125 /* Reserve space for entries */
5127 p += sizeof (dir_entry) * res_id_entries;
5129 /* Write children */
5130 for (l = node->children; l; l = l->next) {
5131 ResTreeNode *child = (ResTreeNode*)l->data;
5133 if (child->win32_res) {
5136 child->offset = p - begin;
5138 /* IMAGE_RESOURCE_DATA_ENTRY */
5139 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5140 size = mono_array_length (child->win32_res->res_data);
5141 data_entry.rde_size = GUINT32_TO_LE (size);
5143 memcpy (p, &data_entry, sizeof (data_entry));
5144 p += sizeof (data_entry);
5146 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5149 resource_tree_encode (child, begin, p, &p);
5153 /* IMAGE_RESOURCE_ENTRY */
5154 for (l = node->children; l; l = l->next) {
5155 ResTreeNode *child = (ResTreeNode*)l->data;
5157 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5158 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5160 memcpy (entries, &dir_entry, sizeof (dir_entry));
5161 entries += sizeof (dir_entry);
5168 resource_tree_free (ResTreeNode * node)
5171 for (list = node->children; list; list = list->next)
5172 resource_tree_free ((ResTreeNode*)list->data);
5173 g_slist_free(node->children);
5178 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5183 MonoReflectionWin32Resource *win32_res;
5186 if (!assemblyb->win32_resources)
5190 * Resources are stored in a three level tree inside the PE file.
5191 * - level one contains a node for each type of resource
5192 * - level two contains a node for each resource
5193 * - level three contains a node for each instance of a resource for a
5194 * specific language.
5197 tree = resource_tree_create (assemblyb->win32_resources);
5199 /* Estimate the size of the encoded tree */
5201 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5202 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5203 size += mono_array_length (win32_res->res_data);
5205 /* Directory structure */
5206 size += mono_array_length (assemblyb->win32_resources) * 256;
5207 p = buf = g_malloc (size);
5209 resource_tree_encode (tree, p, p, &p);
5211 g_assert (p - buf <= size);
5213 assembly->win32_res = g_malloc (p - buf);
5214 assembly->win32_res_size = p - buf;
5215 memcpy (assembly->win32_res, buf, p - buf);
5218 resource_tree_free (tree);
5222 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5224 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5227 p += sizeof (MonoPEResourceDir);
5228 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5229 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5230 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5231 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5232 fixup_resource_directory (res_section, child, rva);
5234 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5235 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5238 p += sizeof (MonoPEResourceDirEntry);
5243 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5246 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5247 g_error ("WriteFile returned %d\n", GetLastError ());
5250 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5253 * mono_image_create_pefile:
5254 * @mb: a module builder object
5256 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5257 * assembly->pefile where it can be easily retrieved later in chunks.
5260 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5262 MonoMSDOSHeader *msdos;
5263 MonoDotNetHeader *header;
5264 MonoSectionTable *section;
5265 MonoCLIHeader *cli_header;
5266 guint32 size, image_size, virtual_base, text_offset;
5267 guint32 header_start, section_start, file_offset, virtual_offset;
5268 MonoDynamicImage *assembly;
5269 MonoReflectionAssemblyBuilder *assemblyb;
5270 MonoDynamicStream pefile_stream = {0};
5271 MonoDynamicStream *pefile = &pefile_stream;
5273 guint32 *rva, value;
5275 static const unsigned char msheader[] = {
5276 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5277 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5280 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5281 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5282 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5283 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5286 assemblyb = mb->assemblyb;
5288 mono_image_basic_init (assemblyb);
5289 assembly = mb->dynamic_image;
5291 assembly->pe_kind = assemblyb->pe_kind;
5292 assembly->machine = assemblyb->machine;
5293 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5294 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5296 mono_image_build_metadata (mb);
5298 if (mb->is_main && assemblyb->resources) {
5299 int len = mono_array_length (assemblyb->resources);
5300 for (i = 0; i < len; ++i)
5301 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5304 if (mb->resources) {
5305 int len = mono_array_length (mb->resources);
5306 for (i = 0; i < len; ++i)
5307 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5310 build_compressed_metadata (assembly);
5313 assembly_add_win32_resources (assembly, assemblyb);
5315 nsections = calc_section_size (assembly);
5317 /* The DOS header and stub */
5318 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5319 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5321 /* the dotnet header */
5322 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5324 /* the section tables */
5325 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5327 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5328 virtual_offset = VIRT_ALIGN;
5331 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5332 if (!assembly->sections [i].size)
5335 file_offset += FILE_ALIGN - 1;
5336 file_offset &= ~(FILE_ALIGN - 1);
5337 virtual_offset += VIRT_ALIGN - 1;
5338 virtual_offset &= ~(VIRT_ALIGN - 1);
5340 assembly->sections [i].offset = file_offset;
5341 assembly->sections [i].rva = virtual_offset;
5343 file_offset += assembly->sections [i].size;
5344 virtual_offset += assembly->sections [i].size;
5345 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5348 file_offset += FILE_ALIGN - 1;
5349 file_offset &= ~(FILE_ALIGN - 1);
5351 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5353 /* back-patch info */
5354 msdos = (MonoMSDOSHeader*)pefile->data;
5355 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5357 header = (MonoDotNetHeader*)(pefile->data + header_start);
5358 header->pesig [0] = 'P';
5359 header->pesig [1] = 'E';
5361 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5362 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5363 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5364 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5365 if (assemblyb->pekind == 1) {
5367 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5370 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5373 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5375 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5376 header->pe.pe_major = 6;
5377 header->pe.pe_minor = 0;
5378 size = assembly->sections [MONO_SECTION_TEXT].size;
5379 size += FILE_ALIGN - 1;
5380 size &= ~(FILE_ALIGN - 1);
5381 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5382 size = assembly->sections [MONO_SECTION_RSRC].size;
5383 size += FILE_ALIGN - 1;
5384 size &= ~(FILE_ALIGN - 1);
5385 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5386 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5387 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5388 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5389 /* pe_rva_entry_point always at the beginning of the text section */
5390 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5392 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5393 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5394 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5395 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5396 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5397 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5398 size = section_start;
5399 size += FILE_ALIGN - 1;
5400 size &= ~(FILE_ALIGN - 1);
5401 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5403 size += VIRT_ALIGN - 1;
5404 size &= ~(VIRT_ALIGN - 1);
5405 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5408 // Translate the PEFileKind value to the value expected by the Windows loader
5414 // PEFileKinds.Dll == 1
5415 // PEFileKinds.ConsoleApplication == 2
5416 // PEFileKinds.WindowApplication == 3
5419 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5420 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5422 if (assemblyb->pekind == 3)
5427 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5429 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5430 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5431 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5432 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5433 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5434 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5436 /* fill data directory entries */
5438 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5439 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5441 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5442 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5444 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5445 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5446 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5447 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5448 /* patch entrypoint name */
5449 if (assemblyb->pekind == 1)
5450 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5452 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5453 /* patch imported function RVA name */
5454 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5455 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5457 /* the import table */
5458 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5459 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5460 /* patch imported dll RVA name and other entries in the dir */
5461 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5462 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5463 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5464 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5465 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5466 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5468 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5469 value = (assembly->text_rva + assembly->imp_names_offset);
5470 *p++ = (value) & 0xff;
5471 *p++ = (value >> 8) & (0xff);
5472 *p++ = (value >> 16) & (0xff);
5473 *p++ = (value >> 24) & (0xff);
5475 /* the CLI header info */
5476 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5477 cli_header->ch_size = GUINT32_FROM_LE (72);
5478 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5479 if (mono_framework_version () > 1)
5480 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5482 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5483 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5484 if (assemblyb->entry_point) {
5485 guint32 table_idx = 0;
5486 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5487 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5488 table_idx = methodb->table_idx;
5490 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5492 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5494 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5496 /* The embedded managed resources */
5497 text_offset = assembly->text_rva + assembly->code.index;
5498 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5499 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5500 text_offset += assembly->resources.index;
5501 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5502 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5503 text_offset += assembly->meta_size;
5504 if (assembly->strong_name_size) {
5505 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5506 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5507 text_offset += assembly->strong_name_size;
5510 /* write the section tables and section content */
5511 section = (MonoSectionTable*)(pefile->data + section_start);
5512 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5513 static const char section_names [][7] = {
5514 ".text", ".rsrc", ".reloc"
5516 if (!assembly->sections [i].size)
5518 strcpy (section->st_name, section_names [i]);
5519 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5520 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5521 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5522 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5523 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5524 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5525 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5529 checked_write_file (file, pefile->data, pefile->index);
5531 mono_dynamic_stream_reset (pefile);
5533 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5534 if (!assembly->sections [i].size)
5537 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5538 g_error ("SetFilePointer returned %d\n", GetLastError ());
5541 case MONO_SECTION_TEXT:
5542 /* patch entry point */
5543 p = (guchar*)(assembly->code.data + 2);
5544 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5545 *p++ = (value) & 0xff;
5546 *p++ = (value >> 8) & 0xff;
5547 *p++ = (value >> 16) & 0xff;
5548 *p++ = (value >> 24) & 0xff;
5550 checked_write_file (file, assembly->code.data, assembly->code.index);
5551 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5552 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5553 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5556 g_free (assembly->image.raw_metadata);
5558 case MONO_SECTION_RELOC: {
5562 guint16 type_and_offset;
5566 g_assert (sizeof (reloc) == 12);
5568 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5569 reloc.block_size = GUINT32_FROM_LE (12);
5572 * the entrypoint is always at the start of the text section
5573 * 3 is IMAGE_REL_BASED_HIGHLOW
5574 * 2 is patch_size_rva - text_rva
5576 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5579 checked_write_file (file, &reloc, sizeof (reloc));
5583 case MONO_SECTION_RSRC:
5584 if (assembly->win32_res) {
5586 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5587 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5588 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5592 g_assert_not_reached ();
5596 /* check that the file is properly padded */
5597 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5598 g_error ("SetFilePointer returned %d\n", GetLastError ());
5599 if (! SetEndOfFile (file))
5600 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5602 mono_dynamic_stream_reset (&assembly->code);
5603 mono_dynamic_stream_reset (&assembly->us);
5604 mono_dynamic_stream_reset (&assembly->blob);
5605 mono_dynamic_stream_reset (&assembly->guid);
5606 mono_dynamic_stream_reset (&assembly->sheap);
5608 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5609 g_hash_table_destroy (assembly->blob_cache);
5610 assembly->blob_cache = NULL;
5613 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5616 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5618 g_assert_not_reached ();
5621 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5623 #ifndef DISABLE_REFLECTION_EMIT
5625 MonoReflectionModule *
5626 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5630 MonoImageOpenStatus status;
5631 MonoDynamicAssembly *assembly;
5632 guint32 module_count;
5633 MonoImage **new_modules;
5634 gboolean *new_modules_loaded;
5636 name = mono_string_to_utf8 (fileName);
5638 image = mono_image_open (name, &status);
5641 if (status == MONO_IMAGE_ERROR_ERRNO)
5642 exc = mono_get_exception_file_not_found (fileName);
5644 exc = mono_get_exception_bad_image_format (name);
5646 mono_raise_exception (exc);
5651 assembly = ab->dynamic_assembly;
5652 image->assembly = (MonoAssembly*)assembly;
5654 module_count = image->assembly->image->module_count;
5655 new_modules = g_new0 (MonoImage *, module_count + 1);
5656 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5658 if (image->assembly->image->modules)
5659 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5660 if (image->assembly->image->modules_loaded)
5661 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5662 new_modules [module_count] = image;
5663 new_modules_loaded [module_count] = TRUE;
5664 mono_image_addref (image);
5666 g_free (image->assembly->image->modules);
5667 image->assembly->image->modules = new_modules;
5668 image->assembly->image->modules_loaded = new_modules_loaded;
5669 image->assembly->image->module_count ++;
5671 mono_assembly_load_references (image, &status);
5673 mono_image_close (image);
5674 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5677 return mono_module_get_object (mono_domain_get (), image);
5680 #endif /* DISABLE_REFLECTION_EMIT */
5683 * We need to return always the same object for MethodInfo, FieldInfo etc..
5684 * but we need to consider the reflected type.
5685 * type uses a different hash, since it uses custom hash/equal functions.
5690 MonoClass *refclass;
5694 reflected_equal (gconstpointer a, gconstpointer b) {
5695 const ReflectedEntry *ea = a;
5696 const ReflectedEntry *eb = b;
5698 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5702 reflected_hash (gconstpointer a) {
5703 const ReflectedEntry *ea = a;
5704 return mono_aligned_addr_hash (ea->item);
5707 #define CHECK_OBJECT(t,p,k) \
5713 mono_domain_lock (domain); \
5714 if (!domain->refobject_hash) \
5715 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5716 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5717 mono_domain_unlock (domain); \
5720 mono_domain_unlock (domain); \
5723 #ifdef HAVE_BOEHM_GC
5724 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5726 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5729 #define CACHE_OBJECT(t,p,o,k) \
5732 ReflectedEntry pe; \
5734 pe.refclass = (k); \
5735 mono_domain_lock (domain); \
5736 if (!domain->refobject_hash) \
5737 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5738 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5740 ReflectedEntry *e = ALLOC_REFENTRY; \
5742 e->refclass = (k); \
5743 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5746 mono_domain_unlock (domain); \
5751 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5753 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5757 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5759 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5762 #ifndef DISABLE_REFLECTION_EMIT
5765 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5767 MonoDynamicImage *image = moduleb->dynamic_image;
5768 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5771 MonoImage **new_modules;
5774 * FIXME: we already created an image in mono_image_basic_init (), but
5775 * we don't know which module it belongs to, since that is only
5776 * determined at assembly save time.
5778 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5779 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5781 moduleb->module.image = &image->image;
5782 moduleb->dynamic_image = image;
5783 register_module (mono_object_domain (moduleb), moduleb, image);
5785 /* register the module with the assembly */
5786 ass = ab->dynamic_assembly->assembly.image;
5787 module_count = ass->module_count;
5788 new_modules = g_new0 (MonoImage *, module_count + 1);
5791 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5792 new_modules [module_count] = &image->image;
5793 mono_image_addref (&image->image);
5795 g_free (ass->modules);
5796 ass->modules = new_modules;
5797 ass->module_count ++;
5804 * mono_assembly_get_object:
5805 * @domain: an app domain
5806 * @assembly: an assembly
5808 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5810 MonoReflectionAssembly*
5811 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5813 static MonoClass *System_Reflection_Assembly;
5814 MonoReflectionAssembly *res;
5816 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5817 if (!System_Reflection_Assembly)
5818 System_Reflection_Assembly = mono_class_from_name (
5819 mono_defaults.corlib, "System.Reflection", "Assembly");
5820 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5821 res->assembly = assembly;
5823 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5828 MonoReflectionModule*
5829 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5831 static MonoClass *System_Reflection_Module;
5832 MonoReflectionModule *res;
5835 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5836 if (!System_Reflection_Module)
5837 System_Reflection_Module = mono_class_from_name (
5838 mono_defaults.corlib, "System.Reflection", "Module");
5839 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5842 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5844 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5845 basename = g_path_get_basename (image->name);
5846 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5847 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5851 if (image->assembly->image == image) {
5852 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5856 if (image->assembly->image->modules) {
5857 for (i = 0; i < image->assembly->image->module_count; i++) {
5858 if (image->assembly->image->modules [i] == image)
5859 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5861 g_assert (res->token);
5865 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5868 MonoReflectionModule*
5869 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5871 static MonoClass *System_Reflection_Module;
5872 MonoReflectionModule *res;
5873 MonoTableInfo *table;
5874 guint32 cols [MONO_FILE_SIZE];
5876 guint32 i, name_idx;
5879 if (!System_Reflection_Module)
5880 System_Reflection_Module = mono_class_from_name (
5881 mono_defaults.corlib, "System.Reflection", "Module");
5882 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5884 table = &image->tables [MONO_TABLE_FILE];
5885 g_assert (table_index < table->rows);
5886 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5889 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5890 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5892 /* Check whenever the row has a corresponding row in the moduleref table */
5893 table = &image->tables [MONO_TABLE_MODULEREF];
5894 for (i = 0; i < table->rows; ++i) {
5895 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5896 val = mono_metadata_string_heap (image, name_idx);
5897 if (strcmp (val, name) == 0)
5898 res->image = image->modules [i];
5901 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5902 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5903 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5904 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5905 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5911 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5913 if ((t1->type != t2->type) ||
5914 (t1->byref != t2->byref))
5918 case MONO_TYPE_VOID:
5919 case MONO_TYPE_BOOLEAN:
5920 case MONO_TYPE_CHAR:
5931 case MONO_TYPE_STRING:
5934 case MONO_TYPE_OBJECT:
5935 case MONO_TYPE_TYPEDBYREF:
5937 case MONO_TYPE_VALUETYPE:
5938 case MONO_TYPE_CLASS:
5939 case MONO_TYPE_SZARRAY:
5940 return t1->data.klass == t2->data.klass;
5942 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5943 case MONO_TYPE_ARRAY:
5944 if (t1->data.array->rank != t2->data.array->rank)
5946 return t1->data.array->eklass == t2->data.array->eklass;
5947 case MONO_TYPE_GENERICINST: {
5949 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5950 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5951 if (i1->type_argc != i2->type_argc)
5953 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5954 &t2->data.generic_class->container_class->byval_arg))
5956 /* FIXME: we should probably just compare the instance pointers directly. */
5957 for (i = 0; i < i1->type_argc; ++i) {
5958 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5964 case MONO_TYPE_MVAR:
5965 return t1->data.generic_param == t2->data.generic_param;
5967 g_error ("implement type compare for %0x!", t1->type);
5975 mymono_metadata_type_hash (MonoType *t1)
5981 hash |= t1->byref << 6; /* do not collide with t1->type values */
5983 case MONO_TYPE_VALUETYPE:
5984 case MONO_TYPE_CLASS:
5985 case MONO_TYPE_SZARRAY:
5986 /* check if the distribution is good enough */
5987 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5989 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5990 case MONO_TYPE_GENERICINST: {
5992 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5993 hash += g_str_hash (t1->data.generic_class->container_class->name);
5995 for (i = 0; i < inst->type_argc; ++i) {
5996 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6005 static MonoReflectionGenericClass*
6006 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6008 static MonoClass *System_Reflection_MonoGenericClass;
6009 MonoReflectionGenericClass *res;
6010 MonoClass *klass, *gklass;
6012 if (!System_Reflection_MonoGenericClass) {
6013 System_Reflection_MonoGenericClass = mono_class_from_name (
6014 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6015 g_assert (System_Reflection_MonoGenericClass);
6018 klass = mono_class_from_mono_type (geninst);
6019 gklass = klass->generic_class->container_class;
6021 mono_class_init (klass);
6024 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6026 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6029 res->type.type = geninst;
6030 g_assert (gklass->reflection_info);
6031 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6032 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6038 verify_safe_for_managed_space (MonoType *type)
6040 switch (type->type) {
6042 case MONO_TYPE_ARRAY:
6043 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6045 return verify_safe_for_managed_space (type->data.type);
6046 case MONO_TYPE_SZARRAY:
6047 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6048 case MONO_TYPE_GENERICINST: {
6049 MonoGenericInst *inst = type->data.generic_class->inst;
6053 for (i = 0; i < inst->type_argc; ++i)
6054 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6060 case MONO_TYPE_MVAR:
6067 * mono_type_get_object:
6068 * @domain: an app domain
6071 * Return an System.MonoType object representing the type @type.
6074 mono_type_get_object (MonoDomain *domain, MonoType *type)
6076 MonoReflectionType *res;
6077 MonoClass *klass = mono_class_from_mono_type (type);
6079 /*we must avoid using @type as it might have come
6080 * from a mono_metadata_type_dup and the caller
6081 * expects that is can be freed.
6082 * Using the right type from
6084 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6086 /* void is very common */
6087 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6088 return (MonoReflectionType*)domain->typeof_void;
6091 * If the vtable of the given class was already created, we can use
6092 * the MonoType from there and avoid all locking and hash table lookups.
6094 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6095 * that the resulting object is diferent.
6097 if (type == &klass->byval_arg && !klass->image->dynamic) {
6098 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6099 if (vtable && vtable->type)
6100 return vtable->type;
6103 mono_domain_lock (domain);
6104 if (!domain->type_hash)
6105 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6106 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6107 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6108 mono_domain_unlock (domain);
6111 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6112 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6113 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6114 mono_g_hash_table_insert (domain->type_hash, type, res);
6115 mono_domain_unlock (domain);
6119 if (!verify_safe_for_managed_space (type)) {
6120 mono_domain_unlock (domain);
6121 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6124 if (klass->reflection_info && !klass->wastypebuilder) {
6125 /* g_assert_not_reached (); */
6126 /* should this be considered an error condition? */
6128 mono_domain_unlock (domain);
6129 return klass->reflection_info;
6132 // FIXME: Get rid of this, do it in the icalls for Type
6133 mono_class_init (klass);
6135 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6137 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6140 mono_g_hash_table_insert (domain->type_hash, type, res);
6142 if (type->type == MONO_TYPE_VOID)
6143 MONO_OBJECT_SETREF (domain, typeof_void, res);
6145 mono_domain_unlock (domain);
6150 * mono_method_get_object:
6151 * @domain: an app domain
6153 * @refclass: the reflected type (can be NULL)
6155 * Return an System.Reflection.MonoMethod object representing the method @method.
6157 MonoReflectionMethod*
6158 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6161 * We use the same C representation for methods and constructors, but the type
6162 * name in C# is different.
6164 static MonoClass *System_Reflection_MonoMethod = NULL;
6165 static MonoClass *System_Reflection_MonoCMethod = NULL;
6166 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6167 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6169 MonoReflectionMethod *ret;
6172 * Don't let static RGCTX invoke wrappers get into
6173 * MonoReflectionMethods.
6175 if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
6176 method = mono_marshal_method_from_wrapper (method);
6178 if (method->is_inflated) {
6179 MonoReflectionGenericMethod *gret;
6181 refclass = method->klass;
6182 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6183 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6184 if (!System_Reflection_MonoGenericCMethod)
6185 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6186 klass = System_Reflection_MonoGenericCMethod;
6188 if (!System_Reflection_MonoGenericMethod)
6189 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6190 klass = System_Reflection_MonoGenericMethod;
6192 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6193 gret->method.method = method;
6194 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6195 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6196 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6200 refclass = method->klass;
6202 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6203 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6204 if (!System_Reflection_MonoCMethod)
6205 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6206 klass = System_Reflection_MonoCMethod;
6209 if (!System_Reflection_MonoMethod)
6210 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6211 klass = System_Reflection_MonoMethod;
6213 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6214 ret->method = method;
6215 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6216 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6220 * mono_field_get_object:
6221 * @domain: an app domain
6225 * Return an System.Reflection.MonoField object representing the field @field
6228 MonoReflectionField*
6229 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6231 MonoReflectionField *res;
6232 static MonoClass *monofield_klass;
6234 CHECK_OBJECT (MonoReflectionField *, field, klass);
6235 if (!monofield_klass)
6236 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6237 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6240 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6241 if (is_field_on_inst (field))
6242 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6244 res->attrs = field->type->attrs;
6245 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6246 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6250 * mono_property_get_object:
6251 * @domain: an app domain
6253 * @property: a property
6255 * Return an System.Reflection.MonoProperty object representing the property @property
6258 MonoReflectionProperty*
6259 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6261 MonoReflectionProperty *res;
6262 static MonoClass *monoproperty_klass;
6264 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6265 if (!monoproperty_klass)
6266 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6267 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6269 res->property = property;
6270 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6274 * mono_event_get_object:
6275 * @domain: an app domain
6279 * Return an System.Reflection.MonoEvent object representing the event @event
6282 MonoReflectionEvent*
6283 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6285 MonoReflectionEvent *res;
6286 static MonoClass *monoevent_klass;
6288 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6289 if (!monoevent_klass)
6290 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6291 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6294 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6298 * mono_get_reflection_missing_object:
6299 * @domain: Domain where the object lives
6301 * Returns the System.Reflection.Missing.Value singleton object
6302 * (of type System.Reflection.Missing).
6304 * Used as the value for ParameterInfo.DefaultValue when Optional
6308 mono_get_reflection_missing_object (MonoDomain *domain)
6311 static MonoClassField *missing_value_field = NULL;
6313 if (!missing_value_field) {
6314 MonoClass *missing_klass;
6315 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6316 mono_class_init (missing_klass);
6317 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6318 g_assert (missing_value_field);
6320 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6326 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6329 *dbnull = mono_get_dbnull_object (domain);
6334 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6336 if (!*reflection_missing)
6337 *reflection_missing = mono_get_reflection_missing_object (domain);
6338 return *reflection_missing;
6342 * mono_param_get_objects:
6343 * @domain: an app domain
6346 * Return an System.Reflection.ParameterInfo array object representing the parameters
6347 * in the method @method.
6350 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6352 static MonoClass *System_Reflection_ParameterInfo;
6353 static MonoClass *System_Reflection_ParameterInfo_array;
6354 MonoArray *res = NULL;
6355 MonoReflectionMethod *member = NULL;
6356 MonoReflectionParameter *param = NULL;
6357 char **names, **blobs = NULL;
6358 guint32 *types = NULL;
6359 MonoType *type = NULL;
6360 MonoObject *dbnull = NULL;
6361 MonoObject *missing = NULL;
6362 MonoMarshalSpec **mspecs;
6363 MonoMethodSignature *sig;
6364 MonoVTable *pinfo_vtable;
6367 if (!System_Reflection_ParameterInfo_array) {
6370 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6371 mono_memory_barrier ();
6372 System_Reflection_ParameterInfo = klass;
6374 klass = mono_array_class_get (klass, 1);
6375 mono_memory_barrier ();
6376 System_Reflection_ParameterInfo_array = klass;
6379 if (!mono_method_signature (method)->param_count)
6380 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6382 /* Note: the cache is based on the address of the signature into the method
6383 * since we already cache MethodInfos with the method as keys.
6385 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6387 sig = mono_method_signature (method);
6388 member = mono_method_get_object (domain, method, NULL);
6389 names = g_new (char *, sig->param_count);
6390 mono_method_get_param_names (method, (const char **) names);
6392 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6393 mono_method_get_marshal_info (method, mspecs);
6395 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6396 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6397 for (i = 0; i < sig->param_count; ++i) {
6398 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6399 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6400 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6401 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6402 param->PositionImpl = i;
6403 param->AttrsImpl = sig->params [i]->attrs;
6405 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6406 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6407 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6409 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6413 blobs = g_new0 (char *, sig->param_count);
6414 types = g_new0 (guint32, sig->param_count);
6415 get_default_param_value_blobs (method, blobs, types);
6418 /* Build MonoType for the type from the Constant Table */
6420 type = g_new0 (MonoType, 1);
6421 type->type = types [i];
6422 type->data.klass = NULL;
6423 if (types [i] == MONO_TYPE_CLASS)
6424 type->data.klass = mono_defaults.object_class;
6425 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6426 /* For enums, types [i] contains the base type */
6428 type->type = MONO_TYPE_VALUETYPE;
6429 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6431 type->data.klass = mono_class_from_mono_type (type);
6433 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6435 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6436 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6437 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6438 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6440 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6446 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6448 mono_array_setref (res, i, param);
6455 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6457 mono_metadata_free_marshal_spec (mspecs [i]);
6460 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6464 * mono_method_body_get_object:
6465 * @domain: an app domain
6468 * Return an System.Reflection.MethodBody object representing the method @method.
6470 MonoReflectionMethodBody*
6471 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6473 static MonoClass *System_Reflection_MethodBody = NULL;
6474 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6475 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6476 MonoReflectionMethodBody *ret;
6477 MonoMethodNormal *mn;
6478 MonoMethodHeader *header;
6479 guint32 method_rva, local_var_sig_token;
6481 unsigned char format, flags;
6484 if (!System_Reflection_MethodBody)
6485 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6486 if (!System_Reflection_LocalVariableInfo)
6487 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6488 if (!System_Reflection_ExceptionHandlingClause)
6489 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6491 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6493 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6494 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6495 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6496 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6498 mn = (MonoMethodNormal *)method;
6499 header = mono_method_get_header (method);
6501 /* Obtain local vars signature token */
6502 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6503 ptr = mono_image_rva_map (method->klass->image, method_rva);
6504 flags = *(const unsigned char *) ptr;
6505 format = flags & METHOD_HEADER_FORMAT_MASK;
6507 case METHOD_HEADER_TINY_FORMAT:
6508 case METHOD_HEADER_TINY_FORMAT1:
6509 local_var_sig_token = 0;
6511 case METHOD_HEADER_FAT_FORMAT:
6515 local_var_sig_token = read32 (ptr);
6518 g_assert_not_reached ();
6521 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6523 ret->init_locals = header->init_locals;
6524 ret->max_stack = header->max_stack;
6525 ret->local_var_sig_token = local_var_sig_token;
6526 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6527 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6530 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6531 for (i = 0; i < header->num_locals; ++i) {
6532 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6533 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6534 info->is_pinned = header->locals [i]->pinned;
6535 info->local_index = i;
6536 mono_array_setref (ret->locals, i, info);
6540 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6541 for (i = 0; i < header->num_clauses; ++i) {
6542 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6543 MonoExceptionClause *clause = &header->clauses [i];
6545 info->flags = clause->flags;
6546 info->try_offset = clause->try_offset;
6547 info->try_length = clause->try_len;
6548 info->handler_offset = clause->handler_offset;
6549 info->handler_length = clause->handler_len;
6550 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6551 info->filter_offset = clause->data.filter_offset;
6552 else if (clause->data.catch_class)
6553 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6555 mono_array_setref (ret->clauses, i, info);
6558 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6563 * mono_get_dbnull_object:
6564 * @domain: Domain where the object lives
6566 * Returns the System.DBNull.Value singleton object
6568 * Used as the value for ParameterInfo.DefaultValue
6571 mono_get_dbnull_object (MonoDomain *domain)
6574 static MonoClassField *dbnull_value_field = NULL;
6576 if (!dbnull_value_field) {
6577 MonoClass *dbnull_klass;
6578 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6579 mono_class_init (dbnull_klass);
6580 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6581 g_assert (dbnull_value_field);
6583 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6589 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6591 guint32 param_index, i, lastp, crow = 0;
6592 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6595 MonoClass *klass = method->klass;
6596 MonoImage *image = klass->image;
6597 MonoMethodSignature *methodsig = mono_method_signature (method);
6599 MonoTableInfo *constt;
6600 MonoTableInfo *methodt;
6601 MonoTableInfo *paramt;
6603 if (!methodsig->param_count)
6606 mono_class_init (klass);
6608 if (klass->image->dynamic) {
6609 MonoReflectionMethodAux *aux;
6610 if (method->is_inflated)
6611 method = ((MonoMethodInflated*)method)->declaring;
6612 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6613 if (aux && aux->param_defaults) {
6614 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6615 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6620 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6621 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6622 constt = &image->tables [MONO_TABLE_CONSTANT];
6624 idx = mono_method_get_index (method) - 1;
6625 g_assert (idx != -1);
6627 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6628 if (idx + 1 < methodt->rows)
6629 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6631 lastp = paramt->rows + 1;
6633 for (i = param_index; i < lastp; ++i) {
6636 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6637 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6639 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6642 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6647 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6648 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6649 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6656 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6661 MonoType *basetype = type;
6666 klass = mono_class_from_mono_type (type);
6667 if (klass->valuetype) {
6668 object = mono_object_new (domain, klass);
6669 retval = ((gchar *) object + sizeof (MonoObject));
6670 if (klass->enumtype)
6671 basetype = mono_class_enum_basetype (klass);
6676 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6683 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6687 memset (assembly, 0, sizeof (MonoAssemblyName));
6689 assembly->culture = "";
6690 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6692 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6695 while (g_ascii_isspace (*p) || *p == ',') {
6704 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6706 assembly->major = strtoul (p, &s, 10);
6707 if (s == p || *s != '.')
6710 assembly->minor = strtoul (p, &s, 10);
6711 if (s == p || *s != '.')
6714 assembly->build = strtoul (p, &s, 10);
6715 if (s == p || *s != '.')
6718 assembly->revision = strtoul (p, &s, 10);
6722 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6724 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6725 assembly->culture = "";
6728 assembly->culture = p;
6729 while (*p && *p != ',') {
6733 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6735 if (strncmp (p, "null", 4) == 0) {
6740 while (*p && *p != ',') {
6743 len = (p - start + 1);
6744 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6745 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6746 g_strlcpy ((char*)assembly->public_key_token, start, len);
6749 while (*p && *p != ',')
6753 while (g_ascii_isspace (*p) || *p == ',') {
6767 * mono_reflection_parse_type:
6770 * Parse a type name as accepted by the GetType () method and output the info
6771 * extracted in the info structure.
6772 * the name param will be mangled, so, make a copy before passing it to this function.
6773 * The fields in info will be valid until the memory pointed to by name is valid.
6775 * See also mono_type_get_name () below.
6777 * Returns: 0 on parse error.
6780 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6781 MonoTypeNameParse *info)
6783 char *start, *p, *w, *temp, *last_point, *startn;
6784 int in_modifiers = 0;
6785 int isbyref = 0, rank, arity = 0, i;
6787 start = p = w = name;
6789 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6790 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6791 info->name = info->name_space = NULL;
6792 info->nested = NULL;
6793 info->modifiers = NULL;
6794 info->type_arguments = NULL;
6796 /* last_point separates the namespace from the name */
6799 while (*p == ' ') p++, start++, w++, name++;
6804 *p = 0; /* NULL terminate the name */
6806 info->nested = g_list_append (info->nested, startn);
6807 /* we have parsed the nesting namespace + name */
6811 info->name_space = start;
6813 info->name = last_point + 1;
6815 info->name_space = (char *)"";
6834 i = strtol (p, &temp, 10);
6851 info->name_space = start;
6853 info->name = last_point + 1;
6855 info->name_space = (char *)"";
6862 if (isbyref) /* only one level allowed by the spec */
6865 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6869 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6875 info->type_arguments = g_ptr_array_new ();
6876 for (i = 0; i < arity; i++) {
6877 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6878 gboolean fqname = FALSE;
6880 g_ptr_array_add (info->type_arguments, subinfo);
6887 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6898 while (*p && (*p != ']'))
6906 if (g_ascii_isspace (*aname)) {
6913 !assembly_name_to_aname (&subinfo->assembly, aname))
6917 if (i + 1 < arity) {
6937 else if (*p == '*') /* '*' means unknown lower bound */
6938 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6945 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6956 if (g_ascii_isspace (*p)) {
6963 return 0; /* missing assembly name */
6964 if (!assembly_name_to_aname (&info->assembly, p))
6970 if (info->assembly.name)
6973 // *w = 0; /* terminate class name */
6975 if (!info->name || !*info->name)
6979 /* add other consistency checks */
6984 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6986 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6990 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6992 gboolean type_resolve = FALSE;
6994 MonoImage *rootimage = image;
6996 if (info->assembly.name) {
6997 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6998 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7000 * This could happen in the AOT compiler case when the search hook is not
7003 assembly = image->assembly;
7005 /* then we must load the assembly ourselve - see #60439 */
7006 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7010 image = assembly->image;
7011 } else if (!image) {
7012 image = mono_defaults.corlib;
7015 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7016 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7017 image = mono_defaults.corlib;
7018 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7025 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7030 gboolean bounded = FALSE;
7033 image = mono_defaults.corlib;
7036 klass = mono_class_from_name_case (image, info->name_space, info->name);
7038 klass = mono_class_from_name (image, info->name_space, info->name);
7041 for (mod = info->nested; mod; mod = mod->next) {
7042 gpointer iter = NULL;
7046 mono_class_init (parent);
7048 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7050 if (g_strcasecmp (klass->name, mod->data) == 0)
7053 if (strcmp (klass->name, mod->data) == 0)
7062 mono_class_init (klass);
7064 if (info->type_arguments) {
7065 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7066 MonoReflectionType *the_type;
7070 for (i = 0; i < info->type_arguments->len; i++) {
7071 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7073 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7074 if (!type_args [i]) {
7080 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7082 instance = mono_reflection_bind_generic_parameters (
7083 the_type, info->type_arguments->len, type_args);
7089 klass = mono_class_from_mono_type (instance);
7092 for (mod = info->modifiers; mod; mod = mod->next) {
7093 modval = GPOINTER_TO_UINT (mod->data);
7094 if (!modval) { /* byref: must be last modifier */
7095 return &klass->this_arg;
7096 } else if (modval == -1) {
7097 klass = mono_ptr_class_get (&klass->byval_arg);
7098 } else if (modval == -2) {
7100 } else { /* array rank */
7101 klass = mono_bounded_array_class_get (klass, modval, bounded);
7103 mono_class_init (klass);
7106 return &klass->byval_arg;
7110 * mono_reflection_get_type:
7111 * @image: a metadata context
7112 * @info: type description structure
7113 * @ignorecase: flag for case-insensitive string compares
7114 * @type_resolve: whenever type resolve was already tried
7116 * Build a MonoType from the type description in @info.
7121 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7122 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7126 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7128 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7132 g_assert (assembly->dynamic);
7134 /* Enumerate all modules */
7137 if (abuilder->modules) {
7138 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7139 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7140 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7146 if (!type && abuilder->loaded_modules) {
7147 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7148 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7149 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7159 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7162 MonoReflectionAssembly *assembly;
7166 if (image && image->dynamic)
7167 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7169 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7172 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7179 *type_resolve = TRUE;
7182 /* Reconstruct the type name */
7183 fullName = g_string_new ("");
7184 if (info->name_space && (info->name_space [0] != '\0'))
7185 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7187 g_string_printf (fullName, info->name);
7188 for (mod = info->nested; mod; mod = mod->next)
7189 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7191 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7193 if (assembly->assembly->dynamic)
7194 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7196 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7199 g_string_free (fullName, TRUE);
7204 mono_reflection_free_type_info (MonoTypeNameParse *info)
7206 g_list_free (info->modifiers);
7207 g_list_free (info->nested);
7209 if (info->type_arguments) {
7212 for (i = 0; i < info->type_arguments->len; i++) {
7213 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7215 mono_reflection_free_type_info (subinfo);
7216 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7220 g_ptr_array_free (info->type_arguments, TRUE);
7225 * mono_reflection_type_from_name:
7227 * @image: a metadata context (can be NULL).
7229 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7230 * it defaults to get the type from @image or, if @image is NULL or loading
7231 * from it fails, uses corlib.
7235 mono_reflection_type_from_name (char *name, MonoImage *image)
7237 MonoType *type = NULL;
7238 MonoTypeNameParse info;
7241 /* Make a copy since parse_type modifies its argument */
7242 tmp = g_strdup (name);
7244 /*g_print ("requested type %s\n", str);*/
7245 if (mono_reflection_parse_type (tmp, &info)) {
7246 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7250 mono_reflection_free_type_info (&info);
7255 * mono_reflection_get_token:
7257 * Return the metadata token of OBJ which should be an object
7258 * representing a metadata element.
7261 mono_reflection_get_token (MonoObject *obj)
7266 klass = obj->vtable->klass;
7268 if (strcmp (klass->name, "MethodBuilder") == 0) {
7269 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7271 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7272 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7273 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7275 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7276 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7277 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7279 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7280 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7281 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7282 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7283 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7284 } else if (strcmp (klass->name, "MonoType") == 0) {
7285 MonoReflectionType *tb = (MonoReflectionType *)obj;
7286 token = mono_class_from_mono_type (tb->type)->type_token;
7287 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7288 strcmp (klass->name, "MonoMethod") == 0 ||
7289 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7290 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7291 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7292 if (m->method->is_inflated) {
7293 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7294 return inflated->declaring->token;
7296 token = m->method->token;
7298 } else if (strcmp (klass->name, "MonoField") == 0) {
7299 MonoReflectionField *f = (MonoReflectionField*)obj;
7301 if (is_field_on_inst (f->field)) {
7302 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7303 int field_index = f->field - dgclass->fields;
7306 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7307 obj = dgclass->field_objects [field_index];
7308 return mono_reflection_get_token (obj);
7310 token = mono_class_get_field_token (f->field);
7311 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7312 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7314 token = mono_class_get_property_token (p->property);
7315 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7316 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7318 token = mono_class_get_event_token (p->event);
7319 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7320 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7322 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7323 } else if (strcmp (klass->name, "Module") == 0) {
7324 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7327 } else if (strcmp (klass->name, "Assembly") == 0) {
7328 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7330 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7331 MonoException *ex = mono_get_exception_not_implemented (msg);
7333 mono_raise_exception (ex);
7340 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7342 int slen, type = t->type;
7343 MonoClass *tklass = t->data.klass;
7349 case MONO_TYPE_BOOLEAN: {
7350 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7355 case MONO_TYPE_CHAR:
7357 case MONO_TYPE_I2: {
7358 guint16 *val = g_malloc (sizeof (guint16));
7363 #if SIZEOF_VOID_P == 4
7369 case MONO_TYPE_I4: {
7370 guint32 *val = g_malloc (sizeof (guint32));
7375 #if SIZEOF_VOID_P == 8
7376 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7380 case MONO_TYPE_I8: {
7381 guint64 *val = g_malloc (sizeof (guint64));
7386 case MONO_TYPE_R8: {
7387 double *val = g_malloc (sizeof (double));
7392 case MONO_TYPE_VALUETYPE:
7393 if (t->data.klass->enumtype) {
7394 type = mono_class_enum_basetype (t->data.klass)->type;
7397 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7400 case MONO_TYPE_STRING:
7401 if (*p == (char)0xFF) {
7405 slen = mono_metadata_decode_value (p, &p);
7407 return mono_string_new_len (mono_domain_get (), p, slen);
7408 case MONO_TYPE_CLASS: {
7411 if (*p == (char)0xFF) {
7416 slen = mono_metadata_decode_value (p, &p);
7417 n = g_memdup (p, slen + 1);
7419 t = mono_reflection_type_from_name (n, image);
7421 g_warning ("Cannot load type '%s'", n);
7425 return mono_type_get_object (mono_domain_get (), t);
7429 case MONO_TYPE_OBJECT: {
7432 MonoClass *subc = NULL;
7437 } else if (subt == 0x0E) {
7438 type = MONO_TYPE_STRING;
7440 } else if (subt == 0x1D) {
7441 MonoType simple_type = {{0}};
7446 /* See Partition II, Appendix B3 */
7447 etype = MONO_TYPE_OBJECT;
7448 type = MONO_TYPE_SZARRAY;
7449 simple_type.type = etype;
7450 tklass = mono_class_from_mono_type (&simple_type);
7452 } else if (subt == 0x55) {
7455 slen = mono_metadata_decode_value (p, &p);
7456 n = g_memdup (p, slen + 1);
7458 t = mono_reflection_type_from_name (n, image);
7460 g_error ("Cannot load type '%s'", n);
7463 subc = mono_class_from_mono_type (t);
7464 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7465 MonoType simple_type = {{0}};
7466 simple_type.type = subt;
7467 subc = mono_class_from_mono_type (&simple_type);
7469 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7471 val = load_cattr_value (image, &subc->byval_arg, p, end);
7472 obj = mono_object_new (mono_domain_get (), subc);
7473 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7477 case MONO_TYPE_SZARRAY: {
7479 guint32 i, alen, basetype;
7482 if (alen == 0xffffffff) {
7486 arr = mono_array_new (mono_domain_get(), tklass, alen);
7487 basetype = tklass->byval_arg.type;
7488 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7489 basetype = mono_class_enum_basetype (tklass)->type;
7494 case MONO_TYPE_BOOLEAN:
7495 for (i = 0; i < alen; i++) {
7496 MonoBoolean val = *p++;
7497 mono_array_set (arr, MonoBoolean, i, val);
7500 case MONO_TYPE_CHAR:
7503 for (i = 0; i < alen; i++) {
7504 guint16 val = read16 (p);
7505 mono_array_set (arr, guint16, i, val);
7512 for (i = 0; i < alen; i++) {
7513 guint32 val = read32 (p);
7514 mono_array_set (arr, guint32, i, val);
7519 for (i = 0; i < alen; i++) {
7522 mono_array_set (arr, double, i, val);
7528 for (i = 0; i < alen; i++) {
7529 guint64 val = read64 (p);
7530 mono_array_set (arr, guint64, i, val);
7534 case MONO_TYPE_CLASS:
7535 case MONO_TYPE_OBJECT:
7536 case MONO_TYPE_STRING:
7537 for (i = 0; i < alen; i++) {
7538 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7539 mono_array_setref (arr, i, item);
7543 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7549 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7555 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7557 static MonoClass *klass;
7558 static MonoMethod *ctor;
7560 void *params [2], *unboxed;
7563 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7565 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7567 params [0] = mono_type_get_object (mono_domain_get (), t);
7569 retval = mono_object_new (mono_domain_get (), klass);
7570 unboxed = mono_object_unbox (retval);
7571 mono_runtime_invoke (ctor, unboxed, params, NULL);
7577 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7579 static MonoClass *klass;
7580 static MonoMethod *ctor;
7582 void *unboxed, *params [2];
7585 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7587 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7590 params [1] = typedarg;
7591 retval = mono_object_new (mono_domain_get (), klass);
7592 unboxed = mono_object_unbox (retval);
7593 mono_runtime_invoke (ctor, unboxed, params, NULL);
7599 type_is_reference (MonoType *type)
7601 switch (type->type) {
7602 case MONO_TYPE_BOOLEAN:
7603 case MONO_TYPE_CHAR:
7616 case MONO_TYPE_VALUETYPE:
7624 free_param_data (MonoMethodSignature *sig, void **params) {
7626 for (i = 0; i < sig->param_count; ++i) {
7627 if (!type_is_reference (sig->params [i]))
7628 g_free (params [i]);
7633 * Find the field index in the metadata FieldDef table.
7636 find_field_index (MonoClass *klass, MonoClassField *field) {
7639 for (i = 0; i < klass->field.count; ++i) {
7640 if (field == &klass->fields [i])
7641 return klass->field.first + 1 + i;
7647 * Find the property index in the metadata Property table.
7650 find_property_index (MonoClass *klass, MonoProperty *property) {
7653 for (i = 0; i < klass->ext->property.count; ++i) {
7654 if (property == &klass->ext->properties [i])
7655 return klass->ext->property.first + 1 + i;
7661 * Find the event index in the metadata Event table.
7664 find_event_index (MonoClass *klass, MonoEvent *event) {
7667 for (i = 0; i < klass->ext->event.count; ++i) {
7668 if (event == &klass->ext->events [i])
7669 return klass->ext->event.first + 1 + i;
7675 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7677 const char *p = (const char*)data;
7679 guint32 i, j, num_named;
7683 mono_class_init (method->klass);
7686 attr = mono_object_new (mono_domain_get (), method->klass);
7687 mono_runtime_invoke (method, attr, NULL, NULL);
7691 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7694 /*g_print ("got attr %s\n", method->klass->name);*/
7696 /* Allocate using alloca so it gets GC tracking */
7697 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7701 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7702 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7706 attr = mono_object_new (mono_domain_get (), method->klass);
7707 mono_runtime_invoke (method, attr, params, NULL);
7708 free_param_data (method->signature, params);
7709 num_named = read16 (named);
7711 for (j = 0; j < num_named; j++) {
7713 char *name, named_type, data_type;
7714 named_type = *named++;
7715 data_type = *named++; /* type of data */
7716 if (data_type == MONO_TYPE_SZARRAY)
7717 data_type = *named++;
7718 if (data_type == MONO_TYPE_ENUM) {
7721 type_len = mono_metadata_decode_blob_size (named, &named);
7722 type_name = g_malloc (type_len + 1);
7723 memcpy (type_name, named, type_len);
7724 type_name [type_len] = 0;
7726 /* FIXME: lookup the type and check type consistency */
7729 name_len = mono_metadata_decode_blob_size (named, &named);
7730 name = g_malloc (name_len + 1);
7731 memcpy (name, named, name_len);
7732 name [name_len] = 0;
7734 if (named_type == 0x53) {
7735 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7736 void *val = load_cattr_value (image, field->type, named, &named);
7737 mono_field_set_value (attr, field, val);
7738 if (!type_is_reference (field->type))
7740 } else if (named_type == 0x54) {
7743 MonoType *prop_type;
7745 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7746 /* can we have more that 1 arg in a custom attr named property? */
7747 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7748 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7749 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7750 mono_property_set_value (prop, attr, pparams, NULL);
7751 if (!type_is_reference (prop_type))
7752 g_free (pparams [0]);
7761 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7763 MonoArray *typedargs, *namedargs;
7764 MonoClass *attrklass;
7765 static MonoMethod *ctor;
7768 const char *p = (const char*)data;
7770 guint32 i, j, num_named;
7773 mono_class_init (method->klass);
7776 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7778 domain = mono_domain_get ();
7780 /* This is for Attributes with no parameters */
7781 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7782 params [0] = mono_method_get_object (domain, method, NULL);
7783 params [1] = params [2] = NULL;
7784 mono_runtime_invoke (method, attr, params, NULL);
7788 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7791 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7795 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7796 MonoObject *obj, *typedarg;
7799 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7800 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7801 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7802 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7803 mono_array_setref (typedargs, i, typedarg);
7805 if (!type_is_reference (mono_method_signature (method)->params [i]))
7810 num_named = read16 (named);
7811 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7813 attrklass = method->klass;
7814 for (j = 0; j < num_named; j++) {
7816 char *name, named_type, data_type;
7817 named_type = *named++;
7818 data_type = *named++; /* type of data */
7819 if (data_type == MONO_TYPE_SZARRAY)
7820 data_type = *named++;
7821 if (data_type == MONO_TYPE_ENUM) {
7824 type_len = mono_metadata_decode_blob_size (named, &named);
7825 type_name = g_malloc (type_len + 1);
7826 memcpy (type_name, named, type_len);
7827 type_name [type_len] = 0;
7829 /* FIXME: lookup the type and check type consistency */
7832 name_len = mono_metadata_decode_blob_size (named, &named);
7833 name = g_malloc (name_len + 1);
7834 memcpy (name, named, name_len);
7835 name [name_len] = 0;
7837 if (named_type == 0x53) {
7838 MonoObject *obj, *typedarg, *namedarg;
7839 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7840 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7842 minfo = mono_field_get_object (domain, NULL, field);
7843 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7844 typedarg = create_cattr_typed_arg (field->type, obj);
7845 namedarg = create_cattr_named_arg (minfo, typedarg);
7846 mono_array_setref (namedargs, j, namedarg);
7847 if (!type_is_reference (field->type))
7849 } else if (named_type == 0x54) {
7850 MonoObject *obj, *typedarg, *namedarg;
7851 MonoType *prop_type;
7853 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7855 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7856 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7857 minfo = mono_property_get_object (domain, NULL, prop);
7858 val = load_cattr_value (image, prop_type, named, &named);
7859 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7860 typedarg = create_cattr_typed_arg (prop_type, obj);
7861 namedarg = create_cattr_named_arg (minfo, typedarg);
7862 mono_array_setref (namedargs, j, namedarg);
7863 if (!type_is_reference (prop_type))
7868 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7869 params [0] = mono_method_get_object (domain, method, NULL);
7870 params [1] = typedargs;
7871 params [2] = namedargs;
7872 mono_runtime_invoke (ctor, attr, params, NULL);
7877 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7883 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7884 for (i = 0; i < cinfo->num_attrs; ++i) {
7885 if (!cinfo->attrs [i].ctor)
7886 /* The cattr type is not finished yet */
7887 /* We should include the type name but cinfo doesn't contain it */
7888 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7889 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7890 mono_array_setref (result, i, attr);
7896 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7903 for (i = 0; i < cinfo->num_attrs; ++i) {
7904 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7908 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7910 for (i = 0; i < cinfo->num_attrs; ++i) {
7911 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7912 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7913 mono_array_setref (result, n, attr);
7921 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7927 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7928 for (i = 0; i < cinfo->num_attrs; ++i) {
7929 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7930 mono_array_setref (result, i, attr);
7936 * mono_custom_attrs_from_index:
7938 * Returns: NULL if no attributes are found or if a loading error occurs.
7941 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7943 guint32 mtoken, i, len;
7944 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7946 MonoCustomAttrInfo *ainfo;
7947 GList *tmp, *list = NULL;
7950 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7952 i = mono_metadata_custom_attrs_from_index (image, idx);
7956 while (i < ca->rows) {
7957 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7959 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7962 len = g_list_length (list);
7965 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7966 ainfo->num_attrs = len;
7967 ainfo->image = image;
7968 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7969 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7970 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7971 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7972 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7973 mtoken |= MONO_TOKEN_METHOD_DEF;
7975 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7976 mtoken |= MONO_TOKEN_MEMBER_REF;
7979 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7982 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7983 if (!ainfo->attrs [i].ctor) {
7984 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7989 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7990 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7991 ainfo->attrs [i].data = (guchar*)data;
7999 mono_custom_attrs_from_method (MonoMethod *method)
8004 * An instantiated method has the same cattrs as the generic method definition.
8006 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8007 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8009 if (method->is_inflated)
8010 method = ((MonoMethodInflated *) method)->declaring;
8012 if (method->dynamic || method->klass->image->dynamic)
8013 return lookup_custom_attr (method->klass->image, method);
8015 idx = mono_method_get_index (method);
8016 idx <<= MONO_CUSTOM_ATTR_BITS;
8017 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8018 return mono_custom_attrs_from_index (method->klass->image, idx);
8022 mono_custom_attrs_from_class (MonoClass *klass)
8026 if (klass->generic_class)
8027 klass = klass->generic_class->container_class;
8029 if (klass->image->dynamic)
8030 return lookup_custom_attr (klass->image, klass);
8032 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8033 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8034 idx <<= MONO_CUSTOM_ATTR_BITS;
8035 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8037 idx = mono_metadata_token_index (klass->type_token);
8038 idx <<= MONO_CUSTOM_ATTR_BITS;
8039 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8041 return mono_custom_attrs_from_index (klass->image, idx);
8045 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8049 if (assembly->image->dynamic)
8050 return lookup_custom_attr (assembly->image, assembly);
8051 idx = 1; /* there is only one assembly */
8052 idx <<= MONO_CUSTOM_ATTR_BITS;
8053 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8054 return mono_custom_attrs_from_index (assembly->image, idx);
8057 static MonoCustomAttrInfo*
8058 mono_custom_attrs_from_module (MonoImage *image)
8063 return lookup_custom_attr (image, image);
8064 idx = 1; /* there is only one module */
8065 idx <<= MONO_CUSTOM_ATTR_BITS;
8066 idx |= MONO_CUSTOM_ATTR_MODULE;
8067 return mono_custom_attrs_from_index (image, idx);
8071 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8075 if (klass->image->dynamic) {
8076 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8077 return lookup_custom_attr (klass->image, property);
8079 idx = find_property_index (klass, property);
8080 idx <<= MONO_CUSTOM_ATTR_BITS;
8081 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8082 return mono_custom_attrs_from_index (klass->image, idx);
8086 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8090 if (klass->image->dynamic) {
8091 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8092 return lookup_custom_attr (klass->image, event);
8094 idx = find_event_index (klass, event);
8095 idx <<= MONO_CUSTOM_ATTR_BITS;
8096 idx |= MONO_CUSTOM_ATTR_EVENT;
8097 return mono_custom_attrs_from_index (klass->image, idx);
8101 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8104 if (klass->image->dynamic) {
8105 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8106 return lookup_custom_attr (klass->image, field);
8108 idx = find_field_index (klass, field);
8109 idx <<= MONO_CUSTOM_ATTR_BITS;
8110 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8111 return mono_custom_attrs_from_index (klass->image, idx);
8115 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8118 guint32 i, idx, method_index;
8119 guint32 param_list, param_last, param_pos, found;
8121 MonoReflectionMethodAux *aux;
8124 * An instantiated method has the same cattrs as the generic method definition.
8126 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8127 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8129 if (method->is_inflated)
8130 method = ((MonoMethodInflated *) method)->declaring;
8132 if (method->klass->image->dynamic) {
8133 MonoCustomAttrInfo *res, *ainfo;
8136 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8137 if (!aux || !aux->param_cattr)
8140 /* Need to copy since it will be freed later */
8141 ainfo = aux->param_cattr [param];
8142 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
8143 res = g_malloc0 (size);
8144 memcpy (res, ainfo, size);
8148 image = method->klass->image;
8149 method_index = mono_method_get_index (method);
8150 ca = &image->tables [MONO_TABLE_METHOD];
8152 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8153 if (method_index == ca->rows) {
8154 ca = &image->tables [MONO_TABLE_PARAM];
8155 param_last = ca->rows + 1;
8157 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8158 ca = &image->tables [MONO_TABLE_PARAM];
8161 for (i = param_list; i < param_last; ++i) {
8162 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8163 if (param_pos == param) {
8171 idx <<= MONO_CUSTOM_ATTR_BITS;
8172 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8173 return mono_custom_attrs_from_index (image, idx);
8177 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8181 for (i = 0; i < ainfo->num_attrs; ++i) {
8182 klass = ainfo->attrs [i].ctor->klass;
8183 if (mono_class_has_parent (klass, attr_klass))
8190 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8197 for (i = 0; i < ainfo->num_attrs; ++i) {
8198 klass = ainfo->attrs [i].ctor->klass;
8199 if (mono_class_has_parent (klass, attr_klass)) {
8204 if (attr_index == -1)
8207 attrs = mono_custom_attrs_construct (ainfo);
8209 return mono_array_get (attrs, MonoObject*, attr_index);
8215 * mono_reflection_get_custom_attrs_info:
8216 * @obj: a reflection object handle
8218 * Return the custom attribute info for attributes defined for the
8219 * reflection handle @obj. The objects.
8222 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8225 MonoCustomAttrInfo *cinfo = NULL;
8227 klass = obj->vtable->klass;
8228 if (klass == mono_defaults.monotype_class) {
8229 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8230 klass = mono_class_from_mono_type (rtype->type);
8231 cinfo = mono_custom_attrs_from_class (klass);
8232 } else if (strcmp ("Assembly", klass->name) == 0) {
8233 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8234 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8235 } else if (strcmp ("Module", klass->name) == 0) {
8236 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8237 cinfo = mono_custom_attrs_from_module (module->image);
8238 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8239 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8240 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8241 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8242 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
8243 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8244 } else if (strcmp ("MonoField", klass->name) == 0) {
8245 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8246 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8247 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8248 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8249 cinfo = mono_custom_attrs_from_method (rmethod->method);
8250 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8251 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8252 cinfo = mono_custom_attrs_from_method (rmethod->method);
8253 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8254 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8255 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8256 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8257 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8258 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8259 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8260 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8261 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8262 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8263 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8264 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8265 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8266 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8267 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8268 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8269 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8270 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8271 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8272 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8273 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8274 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8275 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8276 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8277 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8278 } else { /* handle other types here... */
8279 g_error ("get custom attrs not yet supported for %s", klass->name);
8286 * mono_reflection_get_custom_attrs_by_type:
8287 * @obj: a reflection object handle
8289 * Return an array with all the custom attributes defined of the
8290 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8291 * of that type are returned. The objects are fully build. Return NULL if a loading error
8295 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8298 MonoCustomAttrInfo *cinfo;
8300 cinfo = mono_reflection_get_custom_attrs_info (obj);
8303 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8305 result = mono_custom_attrs_construct (cinfo);
8307 mono_custom_attrs_free (cinfo);
8309 if (mono_loader_get_last_error ())
8311 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8318 * mono_reflection_get_custom_attrs:
8319 * @obj: a reflection object handle
8321 * Return an array with all the custom attributes defined of the
8322 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8326 mono_reflection_get_custom_attrs (MonoObject *obj)
8328 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8332 * mono_reflection_get_custom_attrs_data:
8333 * @obj: a reflection obj handle
8335 * Returns an array of System.Reflection.CustomAttributeData,
8336 * which include information about attributes reflected on
8337 * types loaded using the Reflection Only methods
8340 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8343 MonoCustomAttrInfo *cinfo;
8345 cinfo = mono_reflection_get_custom_attrs_info (obj);
8347 result = mono_custom_attrs_data_construct (cinfo);
8349 mono_custom_attrs_free (cinfo);
8351 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8356 static MonoReflectionType*
8357 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8359 MonoMethod *method_get_underlying_system_type;
8361 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8362 mono_class_get_method_from_name (mono_object_class (t),
8363 "get_UnderlyingSystemType",
8365 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8369 mono_reflection_type_get_handle (MonoReflectionType* t)
8374 t = mono_reflection_type_get_underlying_system_type (t);
8382 * LOCKING: Assumes the loader lock is held.
8384 static MonoMethodSignature*
8385 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
8386 MonoMethodSignature *sig;
8389 count = parameters? mono_array_length (parameters): 0;
8391 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8392 sig->param_count = count;
8393 sig->sentinelpos = -1; /* FIXME */
8394 for (i = 0; i < count; ++i) {
8395 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8396 sig->params [i] = mono_reflection_type_get_handle (pt);
8402 * LOCKING: Assumes the loader lock is held.
8404 static MonoMethodSignature*
8405 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
8406 MonoMethodSignature *sig;
8408 sig = parameters_to_signature (mp, ctor->parameters);
8409 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8410 sig->ret = &mono_defaults.void_class->byval_arg;
8415 * LOCKING: Assumes the loader lock is held.
8417 static MonoMethodSignature*
8418 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
8419 MonoMethodSignature *sig;
8421 sig = parameters_to_signature (mp, method->parameters);
8422 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8423 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8424 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8428 static MonoMethodSignature*
8429 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8430 MonoMethodSignature *sig;
8432 sig = parameters_to_signature (NULL, method->parameters);
8433 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8434 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8435 sig->generic_param_count = 0;
8440 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8442 MonoClass *klass = mono_object_class (prop);
8443 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8444 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8445 *name = mono_string_to_utf8 (pb->name);
8446 *type = pb->type->type;
8448 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8449 *name = g_strdup (p->property->name);
8450 if (p->property->get)
8451 *type = mono_method_signature (p->property->get)->ret;
8453 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8458 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8460 MonoClass *klass = mono_object_class (field);
8461 if (strcmp (klass->name, "FieldBuilder") == 0) {
8462 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8463 *name = mono_string_to_utf8 (fb->name);
8464 *type = fb->type->type;
8466 MonoReflectionField *f = (MonoReflectionField *)field;
8467 *name = g_strdup (mono_field_get_name (f->field));
8468 *type = f->field->type;
8473 * Encode a value in a custom attribute stream of bytes.
8474 * The value to encode is either supplied as an object in argument val
8475 * (valuetypes are boxed), or as a pointer to the data in the
8477 * @type represents the type of the value
8478 * @buffer is the start of the buffer
8479 * @p the current position in the buffer
8480 * @buflen contains the size of the buffer and is used to return the new buffer size
8481 * if this needs to be realloced.
8482 * @retbuffer and @retp return the start and the position of the buffer
8485 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8487 MonoTypeEnum simple_type;
8489 if ((p-buffer) + 10 >= *buflen) {
8492 newbuf = g_realloc (buffer, *buflen);
8493 p = newbuf + (p-buffer);
8497 argval = ((char*)arg + sizeof (MonoObject));
8498 simple_type = type->type;
8500 switch (simple_type) {
8501 case MONO_TYPE_BOOLEAN:
8506 case MONO_TYPE_CHAR:
8509 swap_with_size (p, argval, 2, 1);
8515 swap_with_size (p, argval, 4, 1);
8519 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8529 swap_with_size (p, argval, 8, 1);
8535 swap_with_size (p, argval, 8, 1);
8538 case MONO_TYPE_VALUETYPE:
8539 if (type->data.klass->enumtype) {
8540 simple_type = mono_class_enum_basetype (type->data.klass)->type;
8543 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8546 case MONO_TYPE_STRING: {
8553 str = mono_string_to_utf8 ((MonoString*)arg);
8554 slen = strlen (str);
8555 if ((p-buffer) + 10 + slen >= *buflen) {
8559 newbuf = g_realloc (buffer, *buflen);
8560 p = newbuf + (p-buffer);
8563 mono_metadata_encode_value (slen, p, &p);
8564 memcpy (p, str, slen);
8569 case MONO_TYPE_CLASS: {
8577 k = mono_object_class (arg);
8578 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8579 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8580 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8583 if (rt && (rtc = mono_object_class (rt)) &&
8584 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8585 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8586 arg = (MonoObject *) rt;
8589 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8592 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8593 slen = strlen (str);
8594 if ((p-buffer) + 10 + slen >= *buflen) {
8598 newbuf = g_realloc (buffer, *buflen);
8599 p = newbuf + (p-buffer);
8602 mono_metadata_encode_value (slen, p, &p);
8603 memcpy (p, str, slen);
8608 case MONO_TYPE_SZARRAY: {
8610 MonoClass *eclass, *arg_eclass;
8613 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8616 len = mono_array_length ((MonoArray*)arg);
8618 *p++ = (len >> 8) & 0xff;
8619 *p++ = (len >> 16) & 0xff;
8620 *p++ = (len >> 24) & 0xff;
8622 *retbuffer = buffer;
8623 eclass = type->data.klass;
8624 arg_eclass = mono_object_class (arg)->element_class;
8627 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8628 eclass = mono_defaults.object_class;
8630 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8631 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8632 int elsize = mono_class_array_element_size (arg_eclass);
8633 for (i = 0; i < len; ++i) {
8634 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8637 } else if (eclass->valuetype && arg_eclass->valuetype) {
8638 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8639 int elsize = mono_class_array_element_size (eclass);
8640 for (i = 0; i < len; ++i) {
8641 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8645 for (i = 0; i < len; ++i) {
8646 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8651 case MONO_TYPE_OBJECT: {
8657 * The parameter type is 'object' but the type of the actual
8658 * argument is not. So we have to add type information to the blob
8659 * too. This is completely undocumented in the spec.
8663 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8668 klass = mono_object_class (arg);
8670 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8673 } else if (klass->enumtype) {
8675 } else if (klass == mono_defaults.string_class) {
8676 simple_type = MONO_TYPE_STRING;
8679 } else if (klass->rank == 1) {
8681 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8682 /* See Partition II, Appendix B3 */
8685 *p++ = klass->element_class->byval_arg.type;
8686 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8688 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8689 *p++ = simple_type = klass->byval_arg.type;
8692 g_error ("unhandled type in custom attr");
8694 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8695 slen = strlen (str);
8696 if ((p-buffer) + 10 + slen >= *buflen) {
8700 newbuf = g_realloc (buffer, *buflen);
8701 p = newbuf + (p-buffer);
8704 mono_metadata_encode_value (slen, p, &p);
8705 memcpy (p, str, slen);
8708 simple_type = mono_class_enum_basetype (klass)->type;
8712 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8715 *retbuffer = buffer;
8719 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8721 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8722 char *str = type_get_qualified_name (type, NULL);
8723 int slen = strlen (str);
8727 * This seems to be optional...
8730 mono_metadata_encode_value (slen, p, &p);
8731 memcpy (p, str, slen);
8734 } else if (type->type == MONO_TYPE_OBJECT) {
8736 } else if (type->type == MONO_TYPE_CLASS) {
8737 /* it should be a type: encode_cattr_value () has the check */
8740 mono_metadata_encode_value (type->type, p, &p);
8741 if (type->type == MONO_TYPE_SZARRAY)
8742 /* See the examples in Partition VI, Annex B */
8743 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8750 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8753 /* Preallocate a large enough buffer */
8754 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8755 char *str = type_get_qualified_name (type, NULL);
8758 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8759 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8765 len += strlen (name);
8767 if ((p-buffer) + 20 + len >= *buflen) {
8771 newbuf = g_realloc (buffer, *buflen);
8772 p = newbuf + (p-buffer);
8776 encode_field_or_prop_type (type, p, &p);
8778 len = strlen (name);
8779 mono_metadata_encode_value (len, p, &p);
8780 memcpy (p, name, len);
8782 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8784 *retbuffer = buffer;
8787 #ifndef DISABLE_REFLECTION_EMIT
8790 * mono_reflection_get_custom_attrs_blob:
8791 * @ctor: custom attribute constructor
8792 * @ctorArgs: arguments o the constructor
8798 * Creates the blob of data that needs to be saved in the metadata and that represents
8799 * the custom attributed described by @ctor, @ctorArgs etc.
8800 * Returns: a Byte array representing the blob of data.
8803 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8806 MonoMethodSignature *sig;
8811 MONO_ARCH_SAVE_REGS;
8813 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8814 /* sig is freed later so allocate it in the heap */
8815 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8817 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8820 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8822 p = buffer = g_malloc (buflen);
8823 /* write the prolog */
8826 for (i = 0; i < sig->param_count; ++i) {
8827 arg = mono_array_get (ctorArgs, MonoObject*, i);
8828 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8832 i += mono_array_length (properties);
8834 i += mono_array_length (fields);
8836 *p++ = (i >> 8) & 0xff;
8839 for (i = 0; i < mono_array_length (properties); ++i) {
8843 prop = mono_array_get (properties, gpointer, i);
8844 get_prop_name_and_type (prop, &pname, &ptype);
8845 *p++ = 0x54; /* PROPERTY signature */
8846 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8853 for (i = 0; i < mono_array_length (fields); ++i) {
8857 field = mono_array_get (fields, gpointer, i);
8858 get_field_name_and_type (field, &fname, &ftype);
8859 *p++ = 0x53; /* FIELD signature */
8860 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8865 g_assert (p - buffer <= buflen);
8866 buflen = p - buffer;
8867 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8868 p = mono_array_addr (result, char, 0);
8869 memcpy (p, buffer, buflen);
8871 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8877 * mono_reflection_setup_internal_class:
8878 * @tb: a TypeBuilder object
8880 * Creates a MonoClass that represents the TypeBuilder.
8881 * This is a trick that lets us simplify a lot of reflection code
8882 * (and will allow us to support Build and Run assemblies easier).
8885 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8887 MonoClass *klass, *parent;
8889 MONO_ARCH_SAVE_REGS;
8891 mono_loader_lock ();
8894 /* check so we can compile corlib correctly */
8895 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8896 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8897 parent = tb->parent->type->data.klass;
8899 parent = my_mono_class_from_mono_type (tb->parent->type);
8905 /* the type has already being created: it means we just have to change the parent */
8906 if (tb->type.type) {
8907 klass = mono_class_from_mono_type (tb->type.type);
8908 klass->parent = NULL;
8909 /* fool mono_class_setup_parent */
8910 klass->supertypes = NULL;
8911 mono_class_setup_parent (klass, parent);
8912 mono_class_setup_mono_type (klass);
8913 mono_loader_unlock ();
8917 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
8919 klass->image = &tb->module->dynamic_image->image;
8921 klass->inited = 1; /* we lie to the runtime */
8922 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8923 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8924 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8925 klass->flags = tb->attrs;
8927 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8929 klass->element_class = klass;
8931 MOVING_GC_REGISTER (&klass->reflection_info);
8932 klass->reflection_info = tb;
8934 /* Put into cache so mono_class_get () will find it */
8935 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8937 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8938 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8940 if (parent != NULL) {
8941 mono_class_setup_parent (klass, parent);
8942 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8943 const char *old_n = klass->name;
8944 /* trick to get relative numbering right when compiling corlib */
8945 klass->name = "BuildingObject";
8946 mono_class_setup_parent (klass, mono_defaults.object_class);
8947 klass->name = old_n;
8950 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8951 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8952 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8953 klass->instance_size = sizeof (MonoObject);
8954 klass->size_inited = 1;
8955 mono_class_setup_vtable_general (klass, NULL, 0);
8958 mono_class_setup_mono_type (klass);
8960 mono_class_setup_supertypes (klass);
8963 * FIXME: handle interfaces.
8966 tb->type.type = &klass->byval_arg;
8968 if (tb->nesting_type) {
8969 g_assert (tb->nesting_type->type);
8970 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8973 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8975 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8977 mono_loader_unlock ();
8981 * mono_reflection_setup_generic_class:
8982 * @tb: a TypeBuilder object
8984 * Setup the generic class before adding the first generic parameter.
8987 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8992 * mono_reflection_create_generic_class:
8993 * @tb: a TypeBuilder object
8995 * Creates the generic class after all generic parameters have been added.
8998 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9003 MONO_ARCH_SAVE_REGS;
9005 klass = my_mono_class_from_mono_type (tb->type.type);
9007 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9009 if (klass->generic_container || (count == 0))
9012 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9014 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9016 klass->generic_container->owner.klass = klass;
9017 klass->generic_container->type_argc = count;
9018 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParam) * count);
9020 klass->is_generic = 1;
9022 for (i = 0; i < count; i++) {
9023 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9024 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
9025 /*Make sure we are a diferent type instance */
9026 klass->generic_container->type_params [i].owner = klass->generic_container;
9027 klass->generic_container->type_params [i].pklass = NULL;
9029 g_assert (klass->generic_container->type_params [i].owner);
9032 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9036 * mono_reflection_create_internal_class:
9037 * @tb: a TypeBuilder object
9039 * Actually create the MonoClass that is associated with the TypeBuilder.
9042 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9046 MONO_ARCH_SAVE_REGS;
9048 klass = my_mono_class_from_mono_type (tb->type.type);
9050 mono_loader_lock ();
9051 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9052 MonoReflectionFieldBuilder *fb;
9054 MonoType *enum_basetype;
9056 g_assert (tb->fields != NULL);
9057 g_assert (mono_array_length (tb->fields) >= 1);
9059 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9061 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
9062 mono_loader_unlock ();
9066 enum_basetype = fb->type->type;
9067 klass->element_class = my_mono_class_from_mono_type (enum_basetype);
9068 if (!klass->element_class)
9069 klass->element_class = mono_class_from_mono_type (enum_basetype);
9072 * get the element_class from the current corlib.
9074 ec = default_class_from_mono_type (enum_basetype);
9075 klass->instance_size = ec->instance_size;
9076 klass->size_inited = 1;
9078 * this is almost safe to do with enums and it's needed to be able
9079 * to create objects of the enum type (for use in SetConstant).
9081 /* FIXME: Does this mean enums can't have method overrides ? */
9082 mono_class_setup_vtable_general (klass, NULL, 0);
9084 mono_loader_unlock ();
9087 #endif /* DISABLE_REFLECTION_EMIT */
9089 static MonoMarshalSpec*
9090 mono_marshal_spec_from_builder (MonoMemPool *mp, MonoAssembly *assembly,
9091 MonoReflectionMarshal *minfo)
9093 MonoMarshalSpec *res;
9095 res = mp_g_new0 (mp, MonoMarshalSpec, 1);
9096 res->native = minfo->type;
9098 switch (minfo->type) {
9099 case MONO_NATIVE_LPARRAY:
9100 res->data.array_data.elem_type = minfo->eltype;
9101 if (minfo->has_size) {
9102 res->data.array_data.param_num = minfo->param_num;
9103 res->data.array_data.num_elem = minfo->count;
9104 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9107 res->data.array_data.param_num = -1;
9108 res->data.array_data.num_elem = -1;
9109 res->data.array_data.elem_mult = -1;
9113 case MONO_NATIVE_BYVALTSTR:
9114 case MONO_NATIVE_BYVALARRAY:
9115 res->data.array_data.num_elem = minfo->count;
9118 case MONO_NATIVE_CUSTOM:
9119 if (minfo->marshaltyperef)
9120 res->data.custom_data.custom_name =
9121 type_get_fully_qualified_name (minfo->marshaltyperef->type);
9123 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9133 MonoReflectionMarshal*
9134 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9135 MonoMarshalSpec *spec)
9137 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9138 MonoReflectionMarshal *minfo;
9141 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9142 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9143 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9144 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9147 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9148 minfo->type = spec->native;
9150 switch (minfo->type) {
9151 case MONO_NATIVE_LPARRAY:
9152 minfo->eltype = spec->data.array_data.elem_type;
9153 minfo->count = spec->data.array_data.num_elem;
9154 minfo->param_num = spec->data.array_data.param_num;
9157 case MONO_NATIVE_BYVALTSTR:
9158 case MONO_NATIVE_BYVALARRAY:
9159 minfo->count = spec->data.array_data.num_elem;
9162 case MONO_NATIVE_CUSTOM:
9163 if (spec->data.custom_data.custom_name) {
9164 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9166 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9168 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9170 if (spec->data.custom_data.cookie)
9171 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9182 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9183 ReflectionMethodBuilder *rmb,
9184 MonoMethodSignature *sig)
9187 MonoMethodNormal *pm;
9188 MonoMarshalSpec **specs;
9189 MonoReflectionMethodAux *method_aux;
9195 * Methods created using a MethodBuilder should have their memory allocated
9196 * inside the image mempool, while dynamic methods should have their memory
9199 dynamic = rmb->refs != NULL;
9200 mp = dynamic ? NULL : klass->image->mempool;
9203 g_assert (!klass->generic_class);
9205 mono_loader_lock ();
9207 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9208 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9209 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
9211 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
9213 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
9215 pm = (MonoMethodNormal*)m;
9217 m->dynamic = dynamic;
9219 m->flags = rmb->attrs;
9220 m->iflags = rmb->iattrs;
9221 m->name = mp_string_to_utf8 (mp, rmb->name);
9224 m->skip_visibility = rmb->skip_visibility;
9226 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9228 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9229 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9232 m->signature->pinvoke = 1;
9233 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9234 m->signature->pinvoke = 1;
9236 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9238 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
9239 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
9241 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9243 if (klass->image->dynamic)
9244 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9246 mono_loader_unlock ();
9249 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9250 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9251 MonoMethodHeader *header;
9253 gint32 max_stack, i;
9254 gint32 num_locals = 0;
9255 gint32 num_clauses = 0;
9259 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9260 code_size = rmb->ilgen->code_len;
9261 max_stack = rmb->ilgen->max_stack;
9262 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9263 if (rmb->ilgen->ex_handlers)
9264 num_clauses = method_count_clauses (rmb->ilgen);
9267 code = mono_array_addr (rmb->code, guint8, 0);
9268 code_size = mono_array_length (rmb->code);
9269 /* we probably need to run a verifier on the code... */
9279 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
9280 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9281 header->code_size = code_size;
9282 header->code = mp_g_malloc (mp, code_size);
9283 memcpy ((char*)header->code, code, code_size);
9284 header->max_stack = max_stack;
9285 header->init_locals = rmb->init_locals;
9286 header->num_locals = num_locals;
9288 for (i = 0; i < num_locals; ++i) {
9289 MonoReflectionLocalBuilder *lb =
9290 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9292 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
9293 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9296 header->num_clauses = num_clauses;
9298 header->clauses = method_encode_clauses (mp, (MonoDynamicImage*)klass->image,
9299 rmb->ilgen, num_clauses);
9302 pm->header = header;
9305 if (rmb->generic_params) {
9306 int count = mono_array_length (rmb->generic_params);
9307 MonoGenericContainer *container;
9309 container = rmb->generic_container;
9311 m->is_generic = TRUE;
9312 mono_method_set_generic_container (m, container);
9314 container->type_argc = count;
9315 container->type_params = mp_g_new0 (mp, MonoGenericParam, count);
9316 container->owner.method = m;
9318 for (i = 0; i < count; i++) {
9319 MonoReflectionGenericParam *gp =
9320 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9322 container->type_params [i] = *gp->type.type->data.generic_param;
9325 if (klass->generic_container) {
9326 container->parent = klass->generic_container;
9327 container->context.class_inst = klass->generic_container->context.class_inst;
9329 container->context.method_inst = mono_get_shared_generic_inst (container);
9333 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9337 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9339 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
9340 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9341 for (i = 0; i < rmb->nrefs; ++i)
9342 data [i + 1] = rmb->refs [i];
9347 /* Parameter info */
9350 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9351 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
9352 for (i = 0; i <= m->signature->param_count; ++i) {
9353 MonoReflectionParamBuilder *pb;
9354 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9355 if ((i > 0) && (pb->attrs)) {
9356 /* Make a copy since it might point to a shared type structure */
9357 m->signature->params [i - 1] = mono_metadata_type_dup (mp, m->signature->params [i - 1]);
9358 m->signature->params [i - 1]->attrs = pb->attrs;
9361 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9362 MonoDynamicImage *assembly;
9363 guint32 idx, def_type, len;
9367 if (!method_aux->param_defaults) {
9368 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
9369 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
9371 assembly = (MonoDynamicImage*)klass->image;
9372 idx = encode_constant (assembly, pb->def_value, &def_type);
9373 /* Copy the data from the blob since it might get realloc-ed */
9374 p = assembly->blob.data + idx;
9375 len = mono_metadata_decode_blob_size (p, &p2);
9377 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
9378 method_aux->param_default_types [i] = def_type;
9379 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9383 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
9385 if (!method_aux->param_cattr)
9386 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
9387 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (mp, klass->image, pb->cattrs);
9393 /* Parameter marshalling */
9396 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9397 MonoReflectionParamBuilder *pb;
9398 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9399 if (pb->marshal_info) {
9401 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
9402 specs [pb->position] =
9403 mono_marshal_spec_from_builder (mp, klass->image->assembly, pb->marshal_info);
9407 if (specs != NULL) {
9409 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9410 method_aux->param_marshall = specs;
9413 if (klass->image->dynamic && method_aux)
9414 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9416 mono_loader_unlock ();
9422 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9424 ReflectionMethodBuilder rmb;
9425 MonoMethodSignature *sig;
9427 mono_loader_lock ();
9428 sig = ctor_builder_to_signature (klass->image->mempool, mb);
9429 mono_loader_unlock ();
9431 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9433 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9434 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9436 /* If we are in a generic class, we might be called multiple times from inflate_method */
9437 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9438 /* ilgen is no longer needed */
9446 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9448 ReflectionMethodBuilder rmb;
9449 MonoMethodSignature *sig;
9451 mono_loader_lock ();
9452 sig = method_builder_to_signature (klass->image->mempool, mb);
9453 mono_loader_unlock ();
9455 reflection_methodbuilder_from_method_builder (&rmb, mb);
9457 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9458 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9460 /* If we are in a generic class, we might be called multiple times from inflate_method */
9461 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9462 /* ilgen is no longer needed */
9468 static MonoClassField*
9469 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9471 MonoClassField *field;
9474 field = g_new0 (MonoClassField, 1);
9476 field->name = mono_string_to_utf8 (fb->name);
9477 if (fb->attrs || fb->modreq || fb->modopt) {
9478 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9479 field->type->attrs = fb->attrs;
9481 g_assert (klass->image->dynamic);
9482 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9483 g_free (field->type);
9484 field->type = custom;
9486 field->type = fb->type->type;
9488 if (fb->offset != -1)
9489 field->offset = fb->offset;
9490 field->parent = klass;
9491 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9493 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9499 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9502 MonoReflectionTypeBuilder *tb = NULL;
9503 gboolean is_dynamic = FALSE;
9507 mono_loader_lock ();
9509 domain = mono_object_domain (type);
9511 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9512 tb = (MonoReflectionTypeBuilder *) type;
9515 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9516 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9518 tb = rgi->generic_type;
9522 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9523 if (tb && tb->generic_container)
9524 mono_reflection_create_generic_class (tb);
9526 klass = mono_class_from_mono_type (type->type);
9527 if (!klass->generic_container) {
9528 mono_loader_unlock ();
9532 if (klass->wastypebuilder) {
9533 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9538 mono_loader_unlock ();
9540 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9542 return &geninst->byval_arg;
9546 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9548 MonoGenericClass *gclass;
9549 MonoGenericInst *inst;
9551 g_assert (klass->generic_container);
9553 inst = mono_metadata_get_generic_inst (type_argc, types);
9554 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9556 return mono_generic_class_get_class (gclass);
9559 MonoReflectionMethod*
9560 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9563 MonoMethod *method, *inflated;
9564 MonoMethodInflated *imethod;
9565 MonoReflectionMethodBuilder *mb = NULL;
9566 MonoGenericContext tmp_context;
9567 MonoGenericInst *ginst;
9568 MonoType **type_argv;
9571 MONO_ARCH_SAVE_REGS;
9573 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9574 #ifndef DISABLE_REFLECTION_EMIT
9575 MonoReflectionTypeBuilder *tb;
9578 mb = (MonoReflectionMethodBuilder *) rmethod;
9579 tb = (MonoReflectionTypeBuilder *) mb->type;
9580 klass = mono_class_from_mono_type (tb->type.type);
9582 method = methodbuilder_to_mono_method (klass, mb);
9584 g_assert_not_reached ();
9588 method = rmethod->method;
9591 klass = method->klass;
9593 if (method->is_inflated)
9594 method = ((MonoMethodInflated *) method)->declaring;
9596 count = mono_method_signature (method)->generic_param_count;
9597 if (count != mono_array_length (types))
9600 type_argv = g_new0 (MonoType *, count);
9601 for (i = 0; i < count; i++) {
9602 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9603 type_argv [i] = garg->type;
9605 ginst = mono_metadata_get_generic_inst (count, type_argv);
9608 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9609 tmp_context.method_inst = ginst;
9611 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9612 imethod = (MonoMethodInflated *) inflated;
9614 if (method->klass->image->dynamic) {
9615 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9617 * This table maps metadata structures representing inflated methods/fields
9618 * to the reflection objects representing their generic definitions.
9620 mono_loader_lock ();
9621 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9622 mono_loader_unlock ();
9625 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9628 #ifndef DISABLE_REFLECTION_EMIT
9631 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9633 MonoMethodInflated *imethod;
9634 MonoGenericContext *context;
9638 * With generic code sharing the klass might not be inflated.
9639 * This can happen because classes inflated with their own
9640 * type arguments are "normalized" to the uninflated class.
9642 if (!klass->generic_class)
9645 context = mono_class_get_context (klass);
9647 if (klass->method.count) {
9648 /* Find the already created inflated method */
9649 for (i = 0; i < klass->method.count; ++i) {
9650 g_assert (klass->methods [i]->is_inflated);
9651 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9654 g_assert (i < klass->method.count);
9655 imethod = (MonoMethodInflated*)klass->methods [i];
9657 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9660 if (method->is_generic && method->klass->image->dynamic) {
9661 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9663 mono_loader_lock ();
9664 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9665 mono_loader_unlock ();
9667 return (MonoMethod *) imethod;
9671 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9676 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9678 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9679 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9680 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9682 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9683 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9684 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9685 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9686 method = ((MonoReflectionMethod *) obj)->method;
9688 method = NULL; /* prevent compiler warning */
9689 g_assert_not_reached ();
9692 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9695 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9697 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9698 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9701 MonoGenericClass *gclass;
9702 MonoDynamicGenericClass *dgclass;
9703 MonoClass *klass, *gklass;
9706 MONO_ARCH_SAVE_REGS;
9708 klass = mono_class_from_mono_type (type->type.type);
9709 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9710 gclass = type->type.type->data.generic_class;
9712 g_assert (gclass->is_dynamic);
9713 dgclass = (MonoDynamicGenericClass *) gclass;
9715 if (dgclass->initialized)
9718 gklass = gclass->container_class;
9719 mono_class_init (gklass);
9721 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9722 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9723 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9724 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9725 dgclass->count_events = events ? mono_array_length (events) : 0;
9727 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9728 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9729 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9730 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9731 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9732 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
9733 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
9735 for (i = 0; i < dgclass->count_methods; i++) {
9736 MonoObject *obj = mono_array_get (methods, gpointer, i);
9738 dgclass->methods [i] = inflate_method (type, obj);
9741 for (i = 0; i < dgclass->count_ctors; i++) {
9742 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9744 dgclass->ctors [i] = inflate_method (type, obj);
9747 for (i = 0; i < dgclass->count_fields; i++) {
9748 MonoObject *obj = mono_array_get (fields, gpointer, i);
9749 MonoClassField *field, *inflated_field = NULL;
9751 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9752 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9753 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9754 field = ((MonoReflectionField *) obj)->field;
9756 field = NULL; /* prevent compiler warning */
9757 g_assert_not_reached ();
9760 dgclass->fields [i] = *field;
9761 dgclass->fields [i].parent = klass;
9762 dgclass->fields [i].type = mono_class_inflate_generic_type (
9763 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9764 dgclass->field_generic_types [i] = field->type;
9765 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
9766 dgclass->field_objects [i] = obj;
9768 if (inflated_field) {
9769 g_free (inflated_field);
9771 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9775 for (i = 0; i < dgclass->count_properties; i++) {
9776 MonoObject *obj = mono_array_get (properties, gpointer, i);
9777 MonoProperty *property = &dgclass->properties [i];
9779 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9780 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9782 property->parent = klass;
9783 property->attrs = pb->attrs;
9784 property->name = mono_string_to_utf8 (pb->name);
9786 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9788 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9789 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9790 *property = *((MonoReflectionProperty *) obj)->property;
9791 property->name = g_strdup (property->name);
9794 property->get = inflate_mono_method (klass, property->get, NULL);
9796 property->set = inflate_mono_method (klass, property->set, NULL);
9798 g_assert_not_reached ();
9801 for (i = 0; i < dgclass->count_events; i++) {
9802 MonoObject *obj = mono_array_get (events, gpointer, i);
9803 MonoEvent *event = &dgclass->events [i];
9805 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9806 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9808 event->parent = klass;
9809 event->attrs = eb->attrs;
9810 event->name = mono_string_to_utf8 (eb->name);
9812 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9813 if (eb->remove_method)
9814 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9815 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9816 *event = *((MonoReflectionEvent *) obj)->event;
9817 event->name = g_strdup (event->name);
9820 event->add = inflate_mono_method (klass, event->add, NULL);
9822 event->remove = inflate_mono_method (klass, event->remove, NULL);
9824 g_assert_not_reached ();
9827 dgclass->initialized = TRUE;
9831 ensure_generic_class_runtime_vtable (MonoClass *klass)
9833 MonoClass *gklass = klass->generic_class->container_class;
9836 if (klass->wastypebuilder)
9839 ensure_runtime_vtable (gklass);
9841 klass->method.count = gklass->method.count;
9842 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
9844 for (i = 0; i < klass->method.count; i++) {
9845 klass->methods [i] = mono_class_inflate_generic_method_full (
9846 gklass->methods [i], klass, mono_class_get_context (klass));
9849 klass->interface_count = gklass->interface_count;
9850 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9851 for (i = 0; i < klass->interface_count; ++i) {
9852 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
9853 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
9854 mono_metadata_free_type (iface_type);
9856 ensure_runtime_vtable (klass->interfaces [i]);
9858 klass->interfaces_inited = 1;
9860 /*We can only finish with this klass once it's parent has as well*/
9861 if (gklass->wastypebuilder)
9862 klass->wastypebuilder = TRUE;
9867 ensure_runtime_vtable (MonoClass *klass)
9869 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9872 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
9875 ensure_runtime_vtable (klass->parent);
9878 num = tb->ctors? mono_array_length (tb->ctors): 0;
9879 num += tb->num_methods;
9880 klass->method.count = num;
9881 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
9882 num = tb->ctors? mono_array_length (tb->ctors): 0;
9883 for (i = 0; i < num; ++i)
9884 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9885 num = tb->num_methods;
9887 for (i = 0; i < num; ++i)
9888 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9890 if (tb->interfaces) {
9891 klass->interface_count = mono_array_length (tb->interfaces);
9892 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9893 for (i = 0; i < klass->interface_count; ++i) {
9894 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9895 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9896 ensure_runtime_vtable (klass->interfaces [i]);
9898 klass->interfaces_inited = 1;
9900 } else if (klass->generic_class){
9901 ensure_generic_class_runtime_vtable (klass);
9904 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9905 for (i = 0; i < klass->method.count; ++i)
9906 klass->methods [i]->slot = i;
9908 mono_class_setup_interface_offsets (klass);
9909 mono_class_setup_interface_id (klass);
9913 * The generic vtable is needed even if image->run is not set since some
9914 * runtime code like ves_icall_Type_GetMethodsByName depends on
9915 * method->slot being defined.
9919 * tb->methods could not be freed since it is used for determining
9920 * overrides during dynamic vtable construction.
9925 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9927 MonoReflectionTypeBuilder *tb;
9933 g_assert (klass->image->dynamic);
9935 if (!klass->reflection_info)
9938 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9940 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9944 for (i = 0; i < tb->num_methods; ++i) {
9945 MonoReflectionMethodBuilder *mb =
9946 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9947 if (mb->override_method)
9953 *overrides = g_new0 (MonoMethod*, onum * 2);
9956 for (i = 0; i < tb->num_methods; ++i) {
9957 MonoReflectionMethodBuilder *mb =
9958 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9959 if (mb->override_method) {
9960 (*overrides) [onum * 2] =
9961 mb->override_method->method;
9962 (*overrides) [onum * 2 + 1] =
9965 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9966 g_assert (mb->override_method->method);
9967 g_assert (mb->mhandle);
9974 *num_overrides = onum;
9978 typebuilder_setup_fields (MonoClass *klass)
9980 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9981 MonoReflectionFieldBuilder *fb;
9982 MonoClassField *field;
9983 MonoMemPool *mp = klass->image->mempool;
9986 guint32 len, idx, real_size = 0;
9988 klass->field.count = tb->num_fields;
9989 klass->field.first = 0;
9991 if (tb->class_size) {
9992 g_assert ((tb->packing_size & 0xfffffff0) == 0);
9993 klass->packing_size = tb->packing_size;
9994 real_size = klass->instance_size + tb->class_size;
9997 if (!klass->field.count) {
9998 klass->instance_size = MAX (klass->instance_size, real_size);
10002 klass->fields = mp_g_new0 (mp, MonoClassField, klass->field.count);
10003 mono_class_alloc_ext (klass);
10004 klass->ext->field_def_values = mp_g_new0 (mp, MonoFieldDefaultValue, klass->field.count);
10006 for (i = 0; i < klass->field.count; ++i) {
10007 fb = mono_array_get (tb->fields, gpointer, i);
10008 field = &klass->fields [i];
10009 field->name = mp_string_to_utf8 (mp, fb->name);
10011 field->type = mono_metadata_type_dup (mp, fb->type->type);
10012 field->type->attrs = fb->attrs;
10014 field->type = fb->type->type;
10016 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10017 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10018 if (fb->offset != -1)
10019 field->offset = fb->offset;
10020 field->parent = klass;
10021 fb->handle = field;
10022 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10024 if (fb->def_value) {
10025 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10026 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10027 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10028 /* Copy the data from the blob since it might get realloc-ed */
10029 p = assembly->blob.data + idx;
10030 len = mono_metadata_decode_blob_size (p, &p2);
10032 klass->ext->field_def_values [i].data = mono_mempool_alloc (mp, len);
10033 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10037 klass->instance_size = MAX (klass->instance_size, real_size);
10038 mono_class_layout_fields (klass);
10042 typebuilder_setup_properties (MonoClass *klass)
10044 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10045 MonoReflectionPropertyBuilder *pb;
10046 MonoMemPool *mp = klass->image->mempool;
10047 MonoProperty *properties;
10051 klass->ext = mp_g_new0 (mp, MonoClassExt, 1);
10053 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10054 klass->ext->property.first = 0;
10056 properties = mp_g_new0 (mp, MonoProperty, klass->ext->property.count);
10057 klass->ext->properties = properties;
10058 for (i = 0; i < klass->ext->property.count; ++i) {
10059 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10060 properties [i].parent = klass;
10061 properties [i].attrs = pb->attrs;
10062 properties [i].name = mp_string_to_utf8 (mp, pb->name);
10063 if (pb->get_method)
10064 properties [i].get = pb->get_method->mhandle;
10065 if (pb->set_method)
10066 properties [i].set = pb->set_method->mhandle;
10068 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10072 MonoReflectionEvent *
10073 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10075 MonoEvent *event = g_new0 (MonoEvent, 1);
10079 klass = my_mono_class_from_mono_type (tb->type.type);
10081 event->parent = klass;
10082 event->attrs = eb->attrs;
10083 event->name = mono_string_to_utf8 (eb->name);
10084 if (eb->add_method)
10085 event->add = eb->add_method->mhandle;
10086 if (eb->remove_method)
10087 event->remove = eb->remove_method->mhandle;
10088 if (eb->raise_method)
10089 event->raise = eb->raise_method->mhandle;
10091 if (eb->other_methods) {
10092 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10093 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10094 MonoReflectionMethodBuilder *mb =
10095 mono_array_get (eb->other_methods,
10096 MonoReflectionMethodBuilder*, j);
10097 event->other [j] = mb->mhandle;
10101 return mono_event_get_object (mono_object_domain (tb), klass, event);
10105 typebuilder_setup_events (MonoClass *klass)
10107 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10108 MonoReflectionEventBuilder *eb;
10109 MonoMemPool *mp = klass->image->mempool;
10114 klass->ext = mp_g_new0 (mp, MonoClassExt, 1);
10116 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10117 klass->ext->event.first = 0;
10119 events = mp_g_new0 (mp, MonoEvent, klass->ext->event.count);
10120 klass->ext->events = events;
10121 for (i = 0; i < klass->ext->event.count; ++i) {
10122 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10123 events [i].parent = klass;
10124 events [i].attrs = eb->attrs;
10125 events [i].name = mp_string_to_utf8 (mp, eb->name);
10126 if (eb->add_method)
10127 events [i].add = eb->add_method->mhandle;
10128 if (eb->remove_method)
10129 events [i].remove = eb->remove_method->mhandle;
10130 if (eb->raise_method)
10131 events [i].raise = eb->raise_method->mhandle;
10133 if (eb->other_methods) {
10134 events [i].other = mp_g_new0 (mp, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10135 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10136 MonoReflectionMethodBuilder *mb =
10137 mono_array_get (eb->other_methods,
10138 MonoReflectionMethodBuilder*, j);
10139 events [i].other [j] = mb->mhandle;
10142 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10147 remove_instantiations_of (gpointer key,
10149 gpointer user_data)
10151 MonoType *type = (MonoType*)key;
10152 MonoClass *klass = (MonoClass*)user_data;
10154 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10160 MonoReflectionType*
10161 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10164 MonoDomain* domain;
10165 MonoReflectionType* res;
10168 MONO_ARCH_SAVE_REGS;
10170 domain = mono_object_domain (tb);
10171 klass = my_mono_class_from_mono_type (tb->type.type);
10173 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10176 * we need to lock the domain because the lock will be taken inside
10177 * So, we need to keep the locking order correct.
10179 mono_domain_lock (domain);
10180 mono_loader_lock ();
10181 if (klass->wastypebuilder) {
10182 mono_loader_unlock ();
10183 mono_domain_unlock (domain);
10184 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10187 * Fields to set in klass:
10188 * the various flags: delegate/unicode/contextbound etc.
10190 klass->flags = tb->attrs;
10191 klass->has_cctor = 1;
10192 klass->has_finalize = 1;
10195 if (!((MonoDynamicImage*)klass->image)->run) {
10196 if (klass->generic_container) {
10197 /* FIXME: The code below can't handle generic classes */
10198 klass->wastypebuilder = TRUE;
10199 mono_loader_unlock ();
10200 mono_domain_unlock (domain);
10201 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10206 /* enums are done right away */
10207 if (!klass->enumtype)
10208 ensure_runtime_vtable (klass);
10210 if (tb->subtypes) {
10211 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10212 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10213 mono_class_alloc_ext (klass);
10214 klass->ext->nested_classes = g_list_prepend_mempool (klass->image->mempool, klass->ext->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
10218 klass->nested_classes_inited = TRUE;
10220 /* fields and object layout */
10221 if (klass->parent) {
10222 if (!klass->parent->size_inited)
10223 mono_class_init (klass->parent);
10224 klass->instance_size = klass->parent->instance_size;
10225 klass->sizes.class_size = 0;
10226 klass->min_align = klass->parent->min_align;
10227 /* if the type has no fields we won't call the field_setup
10228 * routine which sets up klass->has_references.
10230 klass->has_references |= klass->parent->has_references;
10232 klass->instance_size = sizeof (MonoObject);
10233 klass->min_align = 1;
10236 /* FIXME: handle packing_size and instance_size */
10237 typebuilder_setup_fields (klass);
10239 typebuilder_setup_properties (klass);
10241 typebuilder_setup_events (klass);
10243 klass->wastypebuilder = TRUE;
10246 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10247 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10248 * we want to return normal System.MonoType objects, so clear these out from the cache.
10250 if (domain->type_hash && klass->generic_container)
10251 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10253 mono_loader_unlock ();
10254 mono_domain_unlock (domain);
10256 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10257 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10258 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10261 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10262 g_assert (res != (MonoReflectionType*)tb);
10268 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10270 MonoGenericParam *param;
10273 MONO_ARCH_SAVE_REGS;
10275 param = g_new0 (MonoGenericParam, 1);
10277 if (gparam->mbuilder) {
10278 if (!gparam->mbuilder->generic_container) {
10279 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10280 MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
10281 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10282 gparam->mbuilder->generic_container->is_method = TRUE;
10284 param->owner = gparam->mbuilder->generic_container;
10285 } else if (gparam->tbuilder) {
10286 if (!gparam->tbuilder->generic_container) {
10287 MonoClass *klass = my_mono_class_from_mono_type (gparam->tbuilder->type.type);
10288 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10289 gparam->tbuilder->generic_container->owner.klass = klass;
10291 param->owner = gparam->tbuilder->generic_container;
10294 param->name = mono_string_to_utf8 (gparam->name);
10295 param->num = gparam->index;
10297 image = &gparam->tbuilder->module->dynamic_image->image;
10298 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10300 gparam->type.type = ¶m->pklass->byval_arg;
10302 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
10303 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10307 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10309 MonoDynamicImage *assembly = sig->module->dynamic_image;
10310 guint32 na = mono_array_length (sig->arguments);
10315 sigbuffer_init (&buf, 32);
10317 sigbuffer_add_value (&buf, 0x07);
10318 sigbuffer_add_value (&buf, na);
10319 for (i = 0; i < na; ++i) {
10320 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10321 encode_reflection_type (assembly, type, &buf);
10324 buflen = buf.p - buf.buf;
10325 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10326 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10327 sigbuffer_free (&buf);
10333 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10335 MonoDynamicImage *assembly = sig->module->dynamic_image;
10336 guint32 na = mono_array_length (sig->arguments);
10341 sigbuffer_init (&buf, 32);
10343 sigbuffer_add_value (&buf, 0x06);
10344 for (i = 0; i < na; ++i) {
10345 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10346 encode_reflection_type (assembly, type, &buf);
10349 buflen = buf.p - buf.buf;
10350 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10351 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10352 sigbuffer_free (&buf);
10358 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10360 ReflectionMethodBuilder rmb;
10361 MonoMethodSignature *sig;
10366 sig = dynamic_method_to_signature (mb);
10368 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10371 * Resolve references.
10374 * Every second entry in the refs array is reserved for storing handle_class,
10375 * which is needed by the ldtoken implementation in the JIT.
10377 rmb.nrefs = mb->nrefs;
10378 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10379 for (i = 0; i < mb->nrefs; i += 2) {
10380 MonoClass *handle_class;
10382 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10384 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10385 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10387 * The referenced DynamicMethod should already be created by the managed
10388 * code, except in the case of circular references. In that case, we store
10389 * method in the refs array, and fix it up later when the referenced
10390 * DynamicMethod is created.
10392 if (method->mhandle) {
10393 ref = method->mhandle;
10395 /* FIXME: GC object stored in unmanaged memory */
10398 /* FIXME: GC object stored in unmanaged memory */
10399 method->referenced_by = g_slist_append (method->referenced_by, mb);
10401 handle_class = mono_defaults.methodhandle_class;
10403 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10406 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10411 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10412 rmb.refs [i + 1] = handle_class;
10415 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10417 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10419 /* Fix up refs entries pointing at us */
10420 for (l = mb->referenced_by; l; l = l->next) {
10421 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10422 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10425 g_assert (method->mhandle);
10427 data = (gpointer*)wrapper->method_data;
10428 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10429 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10430 data [i + 1] = mb->mhandle;
10433 g_slist_free (mb->referenced_by);
10437 /* ilgen is no longer needed */
10441 #endif /* DISABLE_REFLECTION_EMIT */
10444 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10449 mono_runtime_free_method (
10450 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10455 * mono_reflection_is_valid_dynamic_token:
10457 * Returns TRUE if token is valid.
10461 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10463 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10466 #ifndef DISABLE_REFLECTION_EMIT
10469 * mono_reflection_lookup_dynamic_token:
10471 * Finish the Builder object pointed to by TOKEN and return the corresponding
10472 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10473 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10477 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10479 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10483 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10486 g_assert_not_reached ();
10492 handle_class = &klass;
10493 return resolve_object (image, obj, handle_class, context);
10497 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10499 gpointer result = NULL;
10501 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10502 result = mono_string_intern ((MonoString*)obj);
10503 *handle_class = NULL;
10505 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10506 MonoReflectionType *tb = (MonoReflectionType*)obj;
10508 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10509 result = mono_class_from_mono_type (inflated);
10510 mono_metadata_free_type (inflated);
10512 result = mono_class_from_mono_type (tb->type);
10514 *handle_class = mono_defaults.typehandle_class;
10516 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10517 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10518 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10519 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10520 result = ((MonoReflectionMethod*)obj)->method;
10522 result = mono_class_inflate_generic_method (result, context);
10523 *handle_class = mono_defaults.methodhandle_class;
10525 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10526 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10527 result = mb->mhandle;
10529 /* Type is not yet created */
10530 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10532 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10535 * Hopefully this has been filled in by calling CreateType() on the
10539 * TODO: This won't work if the application finishes another
10540 * TypeBuilder instance instead of this one.
10542 result = mb->mhandle;
10545 result = mono_class_inflate_generic_method (result, context);
10546 *handle_class = mono_defaults.methodhandle_class;
10547 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10548 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10550 result = cb->mhandle;
10552 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10554 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10555 result = cb->mhandle;
10558 result = mono_class_inflate_generic_method (result, context);
10559 *handle_class = mono_defaults.methodhandle_class;
10560 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10561 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10563 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
10564 MonoClass *class = mono_class_from_mono_type (inflated);
10565 MonoClassField *inflated_field;
10566 gpointer iter = NULL;
10567 mono_metadata_free_type (inflated);
10568 while ((inflated_field = mono_class_get_fields (class, &iter))) {
10569 if (!strcmp (field->name, inflated_field->name))
10572 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
10573 result = inflated_field;
10577 *handle_class = mono_defaults.fieldhandle_class;
10579 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10580 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10581 result = fb->handle;
10584 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10586 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10587 result = fb->handle;
10590 if (fb->handle && fb->handle->parent->generic_container) {
10591 MonoClass *klass = fb->handle->parent;
10592 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10593 MonoClass *inflated = mono_class_from_mono_type (type);
10595 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
10597 mono_metadata_free_type (type);
10599 *handle_class = mono_defaults.fieldhandle_class;
10600 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10601 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10604 klass = tb->type.type->data.klass;
10605 if (klass->wastypebuilder) {
10606 /* Already created */
10610 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10611 result = tb->type.type->data.klass;
10614 *handle_class = mono_defaults.typehandle_class;
10615 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10616 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10617 MonoMethodSignature *sig;
10620 if (helper->arguments)
10621 nargs = mono_array_length (helper->arguments);
10625 sig = mono_metadata_signature_alloc (image, nargs);
10626 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10627 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10629 if (helper->call_conv == 0) /* unmanaged */
10630 sig->call_convention = helper->unmanaged_call_conv - 1;
10632 if (helper->call_conv & 0x02)
10633 sig->call_convention = MONO_CALL_VARARG;
10635 sig->call_convention = MONO_CALL_DEFAULT;
10637 sig->param_count = nargs;
10638 /* TODO: Copy type ? */
10639 sig->ret = helper->return_type->type;
10640 for (i = 0; i < nargs; ++i) {
10641 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10642 sig->params [i] = rt->type;
10646 *handle_class = NULL;
10647 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10648 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10649 /* Already created by the managed code */
10650 g_assert (method->mhandle);
10651 result = method->mhandle;
10652 *handle_class = mono_defaults.methodhandle_class;
10653 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10654 MonoReflectionType *tb = (MonoReflectionType*)obj;
10655 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10656 result = mono_class_from_mono_type (type);
10657 *handle_class = mono_defaults.typehandle_class;
10659 mono_metadata_free_type (type);
10660 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10661 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10662 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10663 result = mono_class_from_mono_type (type);
10664 *handle_class = mono_defaults.typehandle_class;
10666 mono_metadata_free_type (type);
10667 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10668 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10669 MonoClass *inflated;
10672 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10673 inflated = mono_class_from_mono_type (type);
10675 g_assert (f->fb->handle);
10676 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
10678 mono_metadata_free_type (type);
10679 *handle_class = mono_defaults.fieldhandle_class;
10680 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10681 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10682 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10683 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10684 g_assert (c->cb->mhandle);
10685 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10686 *handle_class = mono_defaults.methodhandle_class;
10687 mono_metadata_free_type (type);
10688 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10689 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10690 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10691 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10692 g_assert (m->mb->mhandle);
10693 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10694 *handle_class = mono_defaults.methodhandle_class;
10695 mono_metadata_free_type (type);
10697 g_print (obj->vtable->klass->name);
10698 g_assert_not_reached ();
10703 #else /* DISABLE_REFLECTION_EMIT */
10706 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10708 g_assert_not_reached ();
10713 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10715 g_assert_not_reached ();
10719 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10721 g_assert_not_reached ();
10725 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10727 g_assert_not_reached ();
10731 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10733 g_assert_not_reached ();
10737 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
10739 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10743 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
10745 g_assert_not_reached ();
10748 MonoReflectionModule *
10749 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
10751 g_assert_not_reached ();
10756 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
10758 g_assert_not_reached ();
10763 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
10765 g_assert_not_reached ();
10770 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
10771 gboolean create_methodspec, gboolean register_token)
10773 g_assert_not_reached ();
10778 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
10783 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10784 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10787 g_assert_not_reached ();
10791 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10794 *num_overrides = 0;
10797 MonoReflectionEvent *
10798 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10800 g_assert_not_reached ();
10804 MonoReflectionType*
10805 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10807 g_assert_not_reached ();
10812 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10814 g_assert_not_reached ();
10818 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10820 g_assert_not_reached ();
10825 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10827 g_assert_not_reached ();
10832 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10837 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10842 #endif /* DISABLE_REFLECTION_EMIT */
10844 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10845 const static guint32 declsec_flags_map[] = {
10846 0x00000000, /* empty */
10847 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10848 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10849 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10850 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10851 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10852 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10853 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10854 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10855 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10856 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10857 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10858 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10859 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10860 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10861 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10862 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10863 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10864 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10868 * Returns flags that includes all available security action associated to the handle.
10869 * @token: metadata token (either for a class or a method)
10870 * @image: image where resides the metadata.
10873 mono_declsec_get_flags (MonoImage *image, guint32 token)
10875 int index = mono_metadata_declsec_from_index (image, token);
10876 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10877 guint32 result = 0;
10881 /* HasSecurity can be present for other, not specially encoded, attributes,
10882 e.g. SuppressUnmanagedCodeSecurityAttribute */
10886 for (i = index; i < t->rows; i++) {
10887 guint32 cols [MONO_DECL_SECURITY_SIZE];
10889 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10890 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10893 action = cols [MONO_DECL_SECURITY_ACTION];
10894 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10895 result |= declsec_flags_map [action];
10897 g_assert_not_reached ();
10904 * Get the security actions (in the form of flags) associated with the specified method.
10906 * @method: The method for which we want the declarative security flags.
10907 * Return the declarative security flags for the method (only).
10909 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10910 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10913 mono_declsec_flags_from_method (MonoMethod *method)
10915 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10916 /* FIXME: No cache (for the moment) */
10917 guint32 idx = mono_method_get_index (method);
10918 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10919 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10920 return mono_declsec_get_flags (method->klass->image, idx);
10926 * Get the security actions (in the form of flags) associated with the specified class.
10928 * @klass: The class for which we want the declarative security flags.
10929 * Return the declarative security flags for the class.
10931 * Note: We cache the flags inside the MonoClass structure as this will get
10932 * called very often (at least for each method).
10935 mono_declsec_flags_from_class (MonoClass *klass)
10937 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10938 if (!klass->ext || !klass->ext->declsec_flags) {
10941 idx = mono_metadata_token_index (klass->type_token);
10942 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10943 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10944 mono_loader_lock ();
10945 mono_class_alloc_ext (klass);
10946 mono_loader_unlock ();
10947 /* we cache the flags on classes */
10948 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10950 return klass->ext->declsec_flags;
10956 * Get the security actions (in the form of flags) associated with the specified assembly.
10958 * @assembly: The assembly for which we want the declarative security flags.
10959 * Return the declarative security flags for the assembly.
10962 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10964 guint32 idx = 1; /* there is only one assembly */
10965 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10966 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10967 return mono_declsec_get_flags (assembly->image, idx);
10972 * Fill actions for the specific index (which may either be an encoded class token or
10973 * an encoded method token) from the metadata image.
10974 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10977 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10978 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10980 MonoBoolean result = FALSE;
10982 guint32 cols [MONO_DECL_SECURITY_SIZE];
10983 int index = mono_metadata_declsec_from_index (image, token);
10986 t = &image->tables [MONO_TABLE_DECLSECURITY];
10987 for (i = index; i < t->rows; i++) {
10988 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10990 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10993 /* if present only replace (class) permissions with method permissions */
10994 /* if empty accept either class or method permissions */
10995 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10996 if (!actions->demand.blob) {
10997 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10998 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10999 actions->demand.blob = (char*) (blob + 2);
11000 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11003 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11004 if (!actions->noncasdemand.blob) {
11005 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11006 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11007 actions->noncasdemand.blob = (char*) (blob + 2);
11008 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11011 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11012 if (!actions->demandchoice.blob) {
11013 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11014 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11015 actions->demandchoice.blob = (char*) (blob + 2);
11016 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11026 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
11027 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11029 guint32 idx = mono_metadata_token_index (klass->type_token);
11030 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11031 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11032 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11036 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11037 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11039 guint32 idx = mono_method_get_index (method);
11040 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11041 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11042 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11046 * Collect all actions (that requires to generate code in mini) assigned for
11047 * the specified method.
11048 * Note: Don't use the content of actions if the function return FALSE.
11051 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11053 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11054 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11055 MonoBoolean result = FALSE;
11058 /* quick exit if no declarative security is present in the metadata */
11059 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11062 /* we want the original as the wrapper is "free" of the security informations */
11063 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11064 method = mono_marshal_method_from_wrapper (method);
11069 /* First we look for method-level attributes */
11070 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11071 mono_class_init (method->klass);
11072 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11074 result = mono_declsec_get_method_demands_params (method, demands,
11075 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11078 /* Here we use (or create) the class declarative cache to look for demands */
11079 flags = mono_declsec_flags_from_class (method->klass);
11080 if (flags & mask) {
11082 mono_class_init (method->klass);
11083 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11085 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11086 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11089 /* The boolean return value is used as a shortcut in case nothing needs to
11090 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11096 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11098 * Note: Don't use the content of actions if the function return FALSE.
11101 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11103 MonoBoolean result = FALSE;
11106 /* quick exit if no declarative security is present in the metadata */
11107 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11110 /* we want the original as the wrapper is "free" of the security informations */
11111 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11112 method = mono_marshal_method_from_wrapper (method);
11117 /* results are independant - zeroize both */
11118 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11119 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11121 /* First we look for method-level attributes */
11122 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11123 mono_class_init (method->klass);
11125 result = mono_declsec_get_method_demands_params (method, cmethod,
11126 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11129 /* Here we use (or create) the class declarative cache to look for demands */
11130 flags = mono_declsec_flags_from_class (method->klass);
11131 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11132 mono_class_init (method->klass);
11134 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11135 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11142 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11144 * @klass The inherited class - this is the class that provides the security check (attributes)
11146 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11148 * Note: Don't use the content of actions if the function return FALSE.
11151 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11153 MonoBoolean result = FALSE;
11156 /* quick exit if no declarative security is present in the metadata */
11157 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11160 /* Here we use (or create) the class declarative cache to look for demands */
11161 flags = mono_declsec_flags_from_class (klass);
11162 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11163 mono_class_init (klass);
11164 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11166 result |= mono_declsec_get_class_demands_params (klass, demands,
11167 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11174 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11176 * Note: Don't use the content of actions if the function return FALSE.
11179 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11181 /* quick exit if no declarative security is present in the metadata */
11182 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11185 /* we want the original as the wrapper is "free" of the security informations */
11186 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11187 method = mono_marshal_method_from_wrapper (method);
11192 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11193 mono_class_init (method->klass);
11194 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11196 return mono_declsec_get_method_demands_params (method, demands,
11197 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11204 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11206 guint32 cols [MONO_DECL_SECURITY_SIZE];
11210 int index = mono_metadata_declsec_from_index (image, token);
11214 t = &image->tables [MONO_TABLE_DECLSECURITY];
11215 for (i = index; i < t->rows; i++) {
11216 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11218 /* shortcut - index are ordered */
11219 if (token != cols [MONO_DECL_SECURITY_PARENT])
11222 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11223 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11224 entry->blob = (char*) (metadata + 2);
11225 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11234 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11236 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11237 guint32 idx = mono_method_get_index (method);
11238 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11239 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11240 return get_declsec_action (method->klass->image, idx, action, entry);
11246 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11249 guint32 flags = mono_declsec_flags_from_class (klass);
11250 if (declsec_flags_map [action] & flags) {
11251 guint32 idx = mono_metadata_token_index (klass->type_token);
11252 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11253 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11254 return get_declsec_action (klass->image, idx, action, entry);
11260 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11262 guint32 idx = 1; /* there is only one assembly */
11263 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11264 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11266 return get_declsec_action (assembly->image, idx, action, entry);
11270 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11272 MonoObject *res, *exc;
11274 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11275 static MonoMethod *method = NULL;
11277 if (!System_Reflection_Emit_TypeBuilder) {
11278 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11279 g_assert (System_Reflection_Emit_TypeBuilder);
11281 if (method == NULL) {
11282 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11287 * The result of mono_type_get_object () might be a System.MonoType but we
11288 * need a TypeBuilder so use klass->reflection_info.
11290 g_assert (klass->reflection_info);
11291 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11293 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11295 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11299 return *(MonoBoolean*)mono_object_unbox (res);