2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/utils/mono-membar.h"
13 #include "mono/metadata/reflection.h"
14 #include "mono/metadata/tabledefs.h"
15 #include "mono/metadata/metadata-internals.h"
16 #include <mono/metadata/profiler-private.h>
17 #include "mono/metadata/class-internals.h"
18 #include "mono/metadata/gc-internal.h"
19 #include "mono/metadata/tokentype.h"
20 #include "mono/metadata/domain-internals.h"
21 #include "mono/metadata/opcodes.h"
22 #include "mono/metadata/assembly.h"
23 #include "mono/metadata/object-internals.h"
24 #include <mono/metadata/exception.h>
25 #include <mono/metadata/marshal.h>
26 #include <mono/metadata/security-manager.h>
35 #include "mono-endian.h"
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/mempool-internals.h>
40 static void* reflection_info_desc = NULL;
41 #define MOVING_GC_REGISTER(addr) do { \
42 if (!reflection_info_desc) { \
44 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
46 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
49 #define MOVING_GC_REGISTER(addr)
58 #define TEXT_OFFSET 512
59 #define CLI_H_SIZE 136
60 #define FILE_ALIGN 512
61 #define VIRT_ALIGN 8192
62 #define START_TEXT_RVA 0x00002000
65 MonoReflectionILGen *ilgen;
66 MonoReflectionType *rtype;
67 MonoArray *parameters;
68 MonoArray *generic_params;
69 MonoGenericContainer *generic_container;
75 guint32 *table_idx; /* note: it's a pointer */
79 MonoBoolean init_locals;
80 MonoBoolean skip_visibility;
81 MonoArray *return_modreq;
82 MonoArray *return_modopt;
83 MonoArray *param_modreq;
84 MonoArray *param_modopt;
85 MonoArray *permissions;
90 int charset, extra_flags, native_cc;
91 MonoString *dll, *dllentry;
92 } ReflectionMethodBuilder;
96 MonoReflectionGenericParam *gparam;
97 } GenericParamTableEntry;
99 const unsigned char table_sizes [MONO_TABLE_NUM] = {
109 MONO_INTERFACEIMPL_SIZE,
110 MONO_MEMBERREF_SIZE, /* 0x0A */
112 MONO_CUSTOM_ATTR_SIZE,
113 MONO_FIELD_MARSHAL_SIZE,
114 MONO_DECL_SECURITY_SIZE,
115 MONO_CLASS_LAYOUT_SIZE,
116 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
117 MONO_STAND_ALONE_SIGNATURE_SIZE,
121 MONO_PROPERTY_MAP_SIZE,
124 MONO_METHOD_SEMA_SIZE,
125 MONO_METHODIMPL_SIZE,
126 MONO_MODULEREF_SIZE, /* 0x1A */
132 MONO_ASSEMBLY_SIZE, /* 0x20 */
133 MONO_ASSEMBLY_PROCESSOR_SIZE,
134 MONO_ASSEMBLYOS_SIZE,
135 MONO_ASSEMBLYREF_SIZE,
136 MONO_ASSEMBLYREFPROC_SIZE,
137 MONO_ASSEMBLYREFOS_SIZE,
141 MONO_NESTED_CLASS_SIZE,
143 MONO_GENERICPARAM_SIZE, /* 0x2A */
144 MONO_METHODSPEC_SIZE,
145 MONO_GENPARCONSTRAINT_SIZE
149 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
150 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
151 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
152 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
153 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
154 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
155 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
156 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
157 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
158 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
159 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
160 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
161 static void ensure_runtime_vtable (MonoClass *klass);
162 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
163 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
164 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
165 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
166 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
167 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
168 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
169 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
171 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
172 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
173 static CRITICAL_SECTION reflection_mutex;
176 mono_reflection_init (void)
178 InitializeCriticalSection (&reflection_mutex);
182 sigbuffer_init (SigBuffer *buf, int size)
184 buf->buf = g_malloc (size);
186 buf->end = buf->buf + size;
190 sigbuffer_make_room (SigBuffer *buf, int size)
192 if (buf->end - buf->p < size) {
193 int new_size = buf->end - buf->buf + size + 32;
194 char *p = g_realloc (buf->buf, new_size);
195 size = buf->p - buf->buf;
198 buf->end = buf->buf + new_size;
203 sigbuffer_add_value (SigBuffer *buf, guint32 val)
205 sigbuffer_make_room (buf, 6);
206 mono_metadata_encode_value (val, buf->p, &buf->p);
210 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
212 sigbuffer_make_room (buf, 1);
218 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
220 sigbuffer_make_room (buf, size);
221 memcpy (buf->p, p, size);
226 sigbuffer_free (SigBuffer *buf)
234 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
238 mp_g_malloc (MonoMemPool *mp, guint size)
241 return mono_mempool_alloc (mp, size);
243 return g_malloc (size);
249 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
253 mp_g_malloc0 (MonoMemPool *mp, guint size)
256 return mono_mempool_alloc0 (mp, size);
258 return g_malloc0 (size);
264 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
265 * memory from the C heap.
268 mp_string_to_utf8 (MonoMemPool *mp, MonoString *s)
271 return mono_string_to_utf8_mp (mp, s);
273 return mono_string_to_utf8 (s);
276 #define mp_g_new(mp,struct_type, n_structs) \
277 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
279 #define mp_g_new0(mp,struct_type, n_structs) \
280 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
283 alloc_table (MonoDynamicTable *table, guint nrows)
286 g_assert (table->columns);
287 if (nrows + 1 >= table->alloc_rows) {
288 while (nrows + 1 >= table->alloc_rows) {
289 if (table->alloc_rows == 0)
290 table->alloc_rows = 16;
292 table->alloc_rows *= 2;
295 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
300 make_room_in_stream (MonoDynamicStream *stream, int size)
302 if (size <= stream->alloc_size)
305 while (stream->alloc_size <= size) {
306 if (stream->alloc_size < 4096)
307 stream->alloc_size = 4096;
309 stream->alloc_size *= 2;
312 stream->data = g_realloc (stream->data, stream->alloc_size);
316 string_heap_insert (MonoDynamicStream *sh, const char *str)
320 gpointer oldkey, oldval;
322 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
323 return GPOINTER_TO_UINT (oldval);
325 len = strlen (str) + 1;
328 make_room_in_stream (sh, idx + len);
331 * We strdup the string even if we already copy them in sh->data
332 * so that the string pointers in the hash remain valid even if
333 * we need to realloc sh->data. We may want to avoid that later.
335 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
336 memcpy (sh->data + idx, str, len);
342 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
344 char *name = mono_string_to_utf8 (str);
346 idx = string_heap_insert (sh, name);
352 string_heap_init (MonoDynamicStream *sh)
355 sh->alloc_size = 4096;
356 sh->data = g_malloc (4096);
357 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
358 string_heap_insert (sh, "");
362 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
366 make_room_in_stream (stream, stream->index + len);
367 memcpy (stream->data + stream->index, data, len);
369 stream->index += len;
371 * align index? Not without adding an additional param that controls it since
372 * we may store a blob value in pieces.
378 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
382 make_room_in_stream (stream, stream->index + len);
383 memset (stream->data + stream->index, 0, len);
385 stream->index += len;
390 stream_data_align (MonoDynamicStream *stream)
393 guint32 count = stream->index % 4;
395 /* we assume the stream data will be aligned */
397 mono_image_add_stream_data (stream, buf, 4 - count);
401 mono_blob_entry_hash (const char* str)
405 len = mono_metadata_decode_blob_size (str, &str);
409 for (str += 1; str < end; str++)
410 h = (h << 5) - h + *str;
418 mono_blob_entry_equal (const char *str1, const char *str2) {
422 len = mono_metadata_decode_blob_size (str1, &end1);
423 len2 = mono_metadata_decode_blob_size (str2, &end2);
426 return memcmp (end1, end2, len) == 0;
430 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
434 gpointer oldkey, oldval;
436 copy = g_malloc (s1+s2);
437 memcpy (copy, b1, s1);
438 memcpy (copy + s1, b2, s2);
439 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
441 idx = GPOINTER_TO_UINT (oldval);
443 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
444 mono_image_add_stream_data (&assembly->blob, b2, s2);
445 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
451 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
455 guint32 size = buf->p - buf->buf;
457 g_assert (size <= (buf->end - buf->buf));
458 mono_metadata_encode_value (size, b, &b);
459 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
463 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
464 * dest may be misaligned.
467 swap_with_size (char *dest, const char* val, int len, int nelem) {
468 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
471 for (elem = 0; elem < nelem; ++elem) {
497 g_assert_not_reached ();
503 memcpy (dest, val, len * nelem);
508 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
512 guint32 idx = 0, len;
514 len = str->length * 2;
515 mono_metadata_encode_value (len, b, &b);
516 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
518 char *swapped = g_malloc (2 * mono_string_length (str));
519 const char *p = (const char*)mono_string_chars (str);
521 swap_with_size (swapped, p, 2, mono_string_length (str));
522 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
526 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
531 /* modified version needed to handle building corlib */
533 my_mono_class_from_mono_type (MonoType *type) {
534 switch (type->type) {
535 case MONO_TYPE_ARRAY:
537 case MONO_TYPE_SZARRAY:
538 case MONO_TYPE_GENERICINST:
539 return mono_class_from_mono_type (type);
542 g_assert (type->data.generic_param->pklass);
543 return type->data.generic_param->pklass;
545 /* should be always valid when we reach this case... */
546 return type->data.klass;
551 default_class_from_mono_type (MonoType *type)
553 switch (type->type) {
554 case MONO_TYPE_OBJECT:
555 return mono_defaults.object_class;
557 return mono_defaults.void_class;
558 case MONO_TYPE_BOOLEAN:
559 return mono_defaults.boolean_class;
561 return mono_defaults.char_class;
563 return mono_defaults.sbyte_class;
565 return mono_defaults.byte_class;
567 return mono_defaults.int16_class;
569 return mono_defaults.uint16_class;
571 return mono_defaults.int32_class;
573 return mono_defaults.uint32_class;
575 return mono_defaults.int_class;
577 return mono_defaults.uint_class;
579 return mono_defaults.int64_class;
581 return mono_defaults.uint64_class;
583 return mono_defaults.single_class;
585 return mono_defaults.double_class;
586 case MONO_TYPE_STRING:
587 return mono_defaults.string_class;
589 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
590 g_assert_not_reached ();
597 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
600 MonoGenericInst *class_inst;
605 class_inst = gclass->context.class_inst;
607 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
608 klass = gclass->container_class;
609 sigbuffer_add_value (buf, klass->byval_arg.type);
610 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
612 sigbuffer_add_value (buf, class_inst->type_argc);
613 for (i = 0; i < class_inst->type_argc; ++i)
614 encode_type (assembly, class_inst->type_argv [i], buf);
619 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
622 g_assert_not_reached ();
627 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
631 case MONO_TYPE_BOOLEAN:
645 case MONO_TYPE_STRING:
646 case MONO_TYPE_OBJECT:
647 case MONO_TYPE_TYPEDBYREF:
648 sigbuffer_add_value (buf, type->type);
651 sigbuffer_add_value (buf, type->type);
652 encode_type (assembly, type->data.type, buf);
654 case MONO_TYPE_SZARRAY:
655 sigbuffer_add_value (buf, type->type);
656 encode_type (assembly, &type->data.klass->byval_arg, buf);
658 case MONO_TYPE_VALUETYPE:
659 case MONO_TYPE_CLASS: {
660 MonoClass *k = mono_class_from_mono_type (type);
662 if (k->generic_container) {
663 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
664 encode_generic_class (assembly, gclass, buf);
667 * Make sure we use the correct type.
669 sigbuffer_add_value (buf, k->byval_arg.type);
671 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
672 * otherwise two typerefs could point to the same type, leading to
673 * verification errors.
675 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
679 case MONO_TYPE_ARRAY:
680 sigbuffer_add_value (buf, type->type);
681 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
682 sigbuffer_add_value (buf, type->data.array->rank);
683 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
684 sigbuffer_add_value (buf, 0);
686 case MONO_TYPE_GENERICINST:
687 encode_generic_class (assembly, type->data.generic_class, buf);
691 sigbuffer_add_value (buf, type->type);
692 sigbuffer_add_value (buf, type->data.generic_param->num);
695 g_error ("need to encode type %x", type->type);
700 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
703 sigbuffer_add_value (buf, MONO_TYPE_VOID);
708 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
709 encode_type (assembly, type->type, buf);
713 g_assert_not_reached ();
718 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
723 for (i = 0; i < mono_array_length (modreq); ++i) {
724 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
725 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
726 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
730 for (i = 0; i < mono_array_length (modopt); ++i) {
731 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
732 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
733 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
739 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
743 guint32 nparams = sig->param_count;
749 sigbuffer_init (&buf, 32);
751 * FIXME: vararg, explicit_this, differenc call_conv values...
753 idx = sig->call_convention;
755 idx |= 0x20; /* hasthis */
756 if (sig->generic_param_count)
757 idx |= 0x10; /* generic */
758 sigbuffer_add_byte (&buf, idx);
759 if (sig->generic_param_count)
760 sigbuffer_add_value (&buf, sig->generic_param_count);
761 sigbuffer_add_value (&buf, nparams);
762 encode_type (assembly, sig->ret, &buf);
763 for (i = 0; i < nparams; ++i) {
764 if (i == sig->sentinelpos)
765 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
766 encode_type (assembly, sig->params [i], &buf);
768 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
769 sigbuffer_free (&buf);
774 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
777 * FIXME: reuse code from method_encode_signature().
781 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
782 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
783 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
786 sigbuffer_init (&buf, 32);
787 /* LAMESPEC: all the call conv spec is foobared */
788 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
789 if (mb->call_conv & 2)
790 idx |= 0x5; /* vararg */
791 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
792 idx |= 0x20; /* hasthis */
794 idx |= 0x10; /* generic */
795 sigbuffer_add_byte (&buf, idx);
797 sigbuffer_add_value (&buf, ngparams);
798 sigbuffer_add_value (&buf, nparams + notypes);
799 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
800 encode_reflection_type (assembly, mb->rtype, &buf);
801 for (i = 0; i < nparams; ++i) {
802 MonoArray *modreq = NULL;
803 MonoArray *modopt = NULL;
804 MonoReflectionType *pt;
806 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
807 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
808 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
809 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
810 encode_custom_modifiers (assembly, modreq, modopt, &buf);
811 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
812 encode_reflection_type (assembly, pt, &buf);
815 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
816 for (i = 0; i < notypes; ++i) {
817 MonoReflectionType *pt;
819 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
820 encode_reflection_type (assembly, pt, &buf);
823 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
824 sigbuffer_free (&buf);
829 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
831 MonoDynamicTable *table;
833 guint32 idx, sig_idx;
834 guint nl = mono_array_length (ilgen->locals);
838 sigbuffer_init (&buf, 32);
839 sigbuffer_add_value (&buf, 0x07);
840 sigbuffer_add_value (&buf, nl);
841 for (i = 0; i < nl; ++i) {
842 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
845 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
847 encode_reflection_type (assembly, lb->type, &buf);
849 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
850 sigbuffer_free (&buf);
852 if (assembly->standalonesig_cache == NULL)
853 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
854 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
858 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
859 idx = table->next_idx ++;
861 alloc_table (table, table->rows);
862 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
864 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
866 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
872 method_count_clauses (MonoReflectionILGen *ilgen)
874 guint32 num_clauses = 0;
877 MonoILExceptionInfo *ex_info;
878 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
879 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
880 if (ex_info->handlers)
881 num_clauses += mono_array_length (ex_info->handlers);
889 static MonoExceptionClause*
890 method_encode_clauses (MonoMemPool *mp, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
892 MonoExceptionClause *clauses;
893 MonoExceptionClause *clause;
894 MonoILExceptionInfo *ex_info;
895 MonoILExceptionBlock *ex_block;
896 guint32 finally_start;
897 int i, j, clause_index;;
899 clauses = mp_g_new0 (mp, MonoExceptionClause, num_clauses);
902 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
903 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
904 finally_start = ex_info->start + ex_info->len;
905 if (!ex_info->handlers)
907 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
908 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
909 clause = &(clauses [clause_index]);
911 clause->flags = ex_block->type;
912 clause->try_offset = ex_info->start;
914 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
915 clause->try_len = finally_start - ex_info->start;
917 clause->try_len = ex_info->len;
918 clause->handler_offset = ex_block->start;
919 clause->handler_len = ex_block->len;
920 if (ex_block->extype) {
921 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
923 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
924 clause->data.filter_offset = ex_block->filter_offset;
926 clause->data.filter_offset = 0;
928 finally_start = ex_block->start + ex_block->len;
938 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
944 gint32 num_locals = 0;
945 gint32 num_exception = 0;
948 char fat_header [12];
951 guint32 local_sig = 0;
952 guint32 header_size = 12;
955 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
956 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
960 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
962 code = mb->ilgen->code;
963 code_size = mb->ilgen->code_len;
964 max_stack = mb->ilgen->max_stack;
965 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
966 if (mb->ilgen->ex_handlers)
967 num_exception = method_count_clauses (mb->ilgen);
971 char *name = mono_string_to_utf8 (mb->name);
972 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
973 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
976 mono_raise_exception (exception);
979 code_size = mono_array_length (code);
980 max_stack = 8; /* we probably need to run a verifier on the code... */
983 stream_data_align (&assembly->code);
985 /* check for exceptions, maxstack, locals */
986 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
988 if (code_size < 64 && !(code_size & 1)) {
989 flags = (code_size << 2) | 0x2;
990 } else if (code_size < 32 && (code_size & 1)) {
991 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
995 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
996 /* add to the fixup todo list */
997 if (mb->ilgen && mb->ilgen->num_token_fixups)
998 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
999 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1000 return assembly->text_rva + idx;
1004 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1006 * FIXME: need to set also the header size in fat_flags.
1007 * (and more sects and init locals flags)
1011 fat_flags |= METHOD_HEADER_MORE_SECTS;
1012 if (mb->init_locals)
1013 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1014 fat_header [0] = fat_flags;
1015 fat_header [1] = (header_size / 4 ) << 4;
1016 short_value = GUINT16_TO_LE (max_stack);
1017 memcpy (fat_header + 2, &short_value, 2);
1018 int_value = GUINT32_TO_LE (code_size);
1019 memcpy (fat_header + 4, &int_value, 4);
1020 int_value = GUINT32_TO_LE (local_sig);
1021 memcpy (fat_header + 8, &int_value, 4);
1022 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1023 /* add to the fixup todo list */
1024 if (mb->ilgen && mb->ilgen->num_token_fixups)
1025 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1027 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1028 if (num_exception) {
1029 unsigned char sheader [4];
1030 MonoILExceptionInfo * ex_info;
1031 MonoILExceptionBlock * ex_block;
1034 stream_data_align (&assembly->code);
1035 /* always use fat format for now */
1036 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1037 num_exception *= 6 * sizeof (guint32);
1038 num_exception += 4; /* include the size of the header */
1039 sheader [1] = num_exception & 0xff;
1040 sheader [2] = (num_exception >> 8) & 0xff;
1041 sheader [3] = (num_exception >> 16) & 0xff;
1042 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1043 /* fat header, so we are already aligned */
1045 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1046 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1047 if (ex_info->handlers) {
1048 int finally_start = ex_info->start + ex_info->len;
1049 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1051 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1053 val = GUINT32_TO_LE (ex_block->type);
1054 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1056 val = GUINT32_TO_LE (ex_info->start);
1057 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1058 /* need fault, too, probably */
1059 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1060 val = GUINT32_TO_LE (finally_start - ex_info->start);
1062 val = GUINT32_TO_LE (ex_info->len);
1063 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1064 /* handler offset */
1065 val = GUINT32_TO_LE (ex_block->start);
1066 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1068 val = GUINT32_TO_LE (ex_block->len);
1069 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1070 finally_start = ex_block->start + ex_block->len;
1071 if (ex_block->extype) {
1072 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1074 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1075 val = ex_block->filter_offset;
1079 val = GUINT32_TO_LE (val);
1080 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1081 /*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",
1082 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);*/
1085 g_error ("No clauses for ex info block %d", i);
1089 return assembly->text_rva + idx;
1093 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1096 MonoDynamicTable *table;
1099 table = &assembly->tables [table_idx];
1101 g_assert (col < table->columns);
1103 values = table->values + table->columns;
1104 for (i = 1; i <= table->rows; ++i) {
1105 if (values [col] == token)
1107 values += table->columns;
1113 * LOCKING: Acquires the loader lock.
1115 static MonoCustomAttrInfo*
1116 lookup_custom_attr (MonoImage *image, gpointer member)
1118 MonoCustomAttrInfo* res;
1120 mono_loader_lock ();
1121 res = mono_property_hash_lookup (image->property_hash, member, MONO_PROP_DYNAMIC_CATTR);
1122 mono_loader_unlock ();
1127 return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1131 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1133 /* FIXME: Need to do more checks */
1134 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1135 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1137 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1144 static MonoCustomAttrInfo*
1145 mono_custom_attrs_from_builders (MonoMemPool *mp, MonoImage *image, MonoArray *cattrs)
1147 int i, index, count, not_visible;
1148 MonoCustomAttrInfo *ainfo;
1149 MonoReflectionCustomAttr *cattr;
1153 /* FIXME: check in assembly the Run flag is set */
1155 count = mono_array_length (cattrs);
1157 /* Skip nonpublic attributes since MS.NET seems to do the same */
1158 /* FIXME: This needs to be done more globally */
1160 for (i = 0; i < count; ++i) {
1161 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1162 if (!custom_attr_visible (image, cattr))
1165 count -= not_visible;
1167 ainfo = mp_g_malloc0 (mp, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1169 ainfo->image = image;
1170 ainfo->num_attrs = count;
1171 ainfo->cached = mp != NULL;
1173 mono_loader_lock ();
1174 for (i = 0; i < count; ++i) {
1175 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1176 if (custom_attr_visible (image, cattr)) {
1177 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1178 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1179 ainfo->attrs [index].ctor = cattr->ctor->method;
1180 ainfo->attrs [index].data = saved;
1181 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1185 mono_loader_unlock ();
1191 * LOCKING: Acquires the loader lock.
1194 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1196 MonoCustomAttrInfo *ainfo, *tmp;
1198 if (!cattrs || !mono_array_length (cattrs))
1201 ainfo = mono_custom_attrs_from_builders (image->mempool, image, cattrs);
1202 mono_loader_lock ();
1203 tmp = mono_property_hash_lookup (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR);
1205 mono_custom_attrs_free (tmp);
1206 mono_property_hash_insert (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1207 mono_loader_unlock ();
1211 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1218 * idx is the table index of the object
1219 * type is one of MONO_CUSTOM_ATTR_*
1222 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1224 MonoDynamicTable *table;
1225 MonoReflectionCustomAttr *cattr;
1227 guint32 count, i, token;
1229 char *p = blob_size;
1231 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1234 count = mono_array_length (cattrs);
1235 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1236 table->rows += count;
1237 alloc_table (table, table->rows);
1238 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1239 idx <<= MONO_CUSTOM_ATTR_BITS;
1241 for (i = 0; i < count; ++i) {
1242 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1243 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1244 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1245 type = mono_metadata_token_index (token);
1246 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1247 switch (mono_metadata_token_table (token)) {
1248 case MONO_TABLE_METHOD:
1249 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1251 case MONO_TABLE_MEMBERREF:
1252 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1255 g_warning ("got wrong token in custom attr");
1258 values [MONO_CUSTOM_ATTR_TYPE] = type;
1260 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1261 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1262 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1263 values += MONO_CUSTOM_ATTR_SIZE;
1269 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1271 MonoDynamicTable *table;
1273 guint32 count, i, idx;
1274 MonoReflectionPermissionSet *perm;
1279 count = mono_array_length (permissions);
1280 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1281 table->rows += count;
1282 alloc_table (table, table->rows);
1284 for (i = 0; i < mono_array_length (permissions); ++i) {
1285 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1287 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1289 idx = mono_metadata_token_index (parent_token);
1290 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1291 switch (mono_metadata_token_table (parent_token)) {
1292 case MONO_TABLE_TYPEDEF:
1293 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1295 case MONO_TABLE_METHOD:
1296 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1298 case MONO_TABLE_ASSEMBLY:
1299 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1302 g_assert_not_reached ();
1305 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1306 values [MONO_DECL_SECURITY_PARENT] = idx;
1307 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1314 * Fill in the MethodDef and ParamDef tables for a method.
1315 * This is used for both normal methods and constructors.
1318 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1320 MonoDynamicTable *table;
1324 /* room in this table is already allocated */
1325 table = &assembly->tables [MONO_TABLE_METHOD];
1326 *mb->table_idx = table->next_idx ++;
1327 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1328 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1329 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1330 values [MONO_METHOD_FLAGS] = mb->attrs;
1331 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1332 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1333 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1335 table = &assembly->tables [MONO_TABLE_PARAM];
1336 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1338 mono_image_add_decl_security (assembly,
1339 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1342 MonoDynamicTable *mtable;
1345 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1346 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1349 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1350 if (mono_array_get (mb->pinfo, gpointer, i))
1353 table->rows += count;
1354 alloc_table (table, table->rows);
1355 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1356 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1357 MonoReflectionParamBuilder *pb;
1358 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1359 values [MONO_PARAM_FLAGS] = pb->attrs;
1360 values [MONO_PARAM_SEQUENCE] = i;
1361 if (pb->name != NULL) {
1362 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1364 values [MONO_PARAM_NAME] = 0;
1366 values += MONO_PARAM_SIZE;
1367 if (pb->marshal_info) {
1369 alloc_table (mtable, mtable->rows);
1370 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1371 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1372 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1374 pb->table_idx = table->next_idx++;
1375 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1376 guint32 field_type = 0;
1377 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1379 alloc_table (mtable, mtable->rows);
1380 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1381 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1382 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1383 mvalues [MONO_CONSTANT_TYPE] = field_type;
1384 mvalues [MONO_CONSTANT_PADDING] = 0;
1392 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1394 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1396 rmb->ilgen = mb->ilgen;
1397 rmb->rtype = mb->rtype;
1398 rmb->parameters = mb->parameters;
1399 rmb->generic_params = mb->generic_params;
1400 rmb->generic_container = mb->generic_container;
1401 rmb->opt_types = NULL;
1402 rmb->pinfo = mb->pinfo;
1403 rmb->attrs = mb->attrs;
1404 rmb->iattrs = mb->iattrs;
1405 rmb->call_conv = mb->call_conv;
1406 rmb->code = mb->code;
1407 rmb->type = mb->type;
1408 rmb->name = mb->name;
1409 rmb->table_idx = &mb->table_idx;
1410 rmb->init_locals = mb->init_locals;
1411 rmb->skip_visibility = FALSE;
1412 rmb->return_modreq = mb->return_modreq;
1413 rmb->return_modopt = mb->return_modopt;
1414 rmb->param_modreq = mb->param_modreq;
1415 rmb->param_modopt = mb->param_modopt;
1416 rmb->permissions = mb->permissions;
1417 rmb->mhandle = mb->mhandle;
1422 rmb->charset = mb->charset;
1423 rmb->extra_flags = mb->extra_flags;
1424 rmb->native_cc = mb->native_cc;
1425 rmb->dllentry = mb->dllentry;
1431 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1433 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1435 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1437 rmb->ilgen = mb->ilgen;
1438 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1439 rmb->parameters = mb->parameters;
1440 rmb->generic_params = NULL;
1441 rmb->generic_container = NULL;
1442 rmb->opt_types = NULL;
1443 rmb->pinfo = mb->pinfo;
1444 rmb->attrs = mb->attrs;
1445 rmb->iattrs = mb->iattrs;
1446 rmb->call_conv = mb->call_conv;
1448 rmb->type = mb->type;
1449 rmb->name = mono_string_new (mono_domain_get (), name);
1450 rmb->table_idx = &mb->table_idx;
1451 rmb->init_locals = mb->init_locals;
1452 rmb->skip_visibility = FALSE;
1453 rmb->return_modreq = NULL;
1454 rmb->return_modopt = NULL;
1455 rmb->param_modreq = mb->param_modreq;
1456 rmb->param_modopt = mb->param_modopt;
1457 rmb->permissions = mb->permissions;
1458 rmb->mhandle = mb->mhandle;
1464 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1466 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1468 rmb->ilgen = mb->ilgen;
1469 rmb->rtype = mb->rtype;
1470 rmb->parameters = mb->parameters;
1471 rmb->generic_params = NULL;
1472 rmb->generic_container = NULL;
1473 rmb->opt_types = NULL;
1475 rmb->attrs = mb->attrs;
1477 rmb->call_conv = mb->call_conv;
1479 rmb->type = (MonoObject *) mb->owner;
1480 rmb->name = mb->name;
1481 rmb->table_idx = NULL;
1482 rmb->init_locals = mb->init_locals;
1483 rmb->skip_visibility = mb->skip_visibility;
1484 rmb->return_modreq = NULL;
1485 rmb->return_modopt = NULL;
1486 rmb->param_modreq = NULL;
1487 rmb->param_modopt = NULL;
1488 rmb->permissions = NULL;
1489 rmb->mhandle = mb->mhandle;
1495 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1497 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1498 MonoDynamicTable *table;
1502 if (!mb->override_method)
1505 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1507 alloc_table (table, table->rows);
1508 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1509 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1510 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1512 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1513 switch (mono_metadata_token_table (tok)) {
1514 case MONO_TABLE_MEMBERREF:
1515 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1517 case MONO_TABLE_METHOD:
1518 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1521 g_assert_not_reached ();
1523 values [MONO_METHODIMPL_DECLARATION] = tok;
1527 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1529 MonoDynamicTable *table;
1531 ReflectionMethodBuilder rmb;
1534 reflection_methodbuilder_from_method_builder (&rmb, mb);
1536 mono_image_basic_method (&rmb, assembly);
1537 mb->table_idx = *rmb.table_idx;
1539 if (mb->dll) { /* It's a P/Invoke method */
1541 /* map CharSet values to on-disk values */
1542 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1543 int extra_flags = mb->extra_flags;
1544 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1546 alloc_table (table, table->rows);
1547 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1549 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1550 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1552 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1554 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1555 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1556 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1557 table = &assembly->tables [MONO_TABLE_MODULEREF];
1559 alloc_table (table, table->rows);
1560 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1561 values [MONO_IMPLMAP_SCOPE] = table->rows;
1565 if (mb->generic_params) {
1566 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1567 table->rows += mono_array_length (mb->generic_params);
1568 alloc_table (table, table->rows);
1569 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1570 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1572 mono_image_get_generic_param_info (
1573 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1580 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1582 ReflectionMethodBuilder rmb;
1584 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1586 mono_image_basic_method (&rmb, assembly);
1587 mb->table_idx = *rmb.table_idx;
1591 type_get_fully_qualified_name (MonoType *type)
1593 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1597 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1601 klass = my_mono_class_from_mono_type (type);
1603 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1604 ta = klass->image->assembly;
1605 if (ta->dynamic || (ta == ass)) {
1606 if (klass->generic_class || klass->generic_container)
1607 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1608 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1610 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1613 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1617 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1622 if (!assembly->save)
1625 sigbuffer_init (&buf, 32);
1627 sigbuffer_add_value (&buf, 0x06);
1628 /* encode custom attributes before the type */
1629 /* FIXME: This should probably go in encode_type () */
1630 if (type->num_mods) {
1631 for (i = 0; i < type->num_mods; ++i) {
1632 if (type->modifiers [i].required)
1633 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1635 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1636 sigbuffer_add_value (&buf, type->modifiers [i].token);
1639 encode_type (assembly, type, &buf);
1640 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1641 sigbuffer_free (&buf);
1646 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1651 sigbuffer_init (&buf, 32);
1653 sigbuffer_add_value (&buf, 0x06);
1654 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1655 /* encode custom attributes before the type */
1656 encode_reflection_type (assembly, fb->type, &buf);
1657 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1658 sigbuffer_free (&buf);
1663 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1664 char blob_size [64];
1665 char *b = blob_size;
1668 guint32 idx = 0, len = 0, dummy = 0;
1670 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1671 guint32 fpa_double [2];
1676 p = buf = g_malloc (64);
1678 *ret_type = MONO_TYPE_CLASS;
1680 box_val = (char*)&dummy;
1682 box_val = ((char*)val) + sizeof (MonoObject);
1683 *ret_type = val->vtable->klass->byval_arg.type;
1686 switch (*ret_type) {
1687 case MONO_TYPE_BOOLEAN:
1692 case MONO_TYPE_CHAR:
1709 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1710 fpa_p = (guint32*)box_val;
1711 fpa_double [0] = fpa_p [1];
1712 fpa_double [1] = fpa_p [0];
1713 box_val = (char*)fpa_double;
1717 case MONO_TYPE_VALUETYPE:
1718 if (val->vtable->klass->enumtype) {
1719 *ret_type = val->vtable->klass->enum_basetype->type;
1722 g_error ("we can't encode valuetypes");
1723 case MONO_TYPE_CLASS:
1725 case MONO_TYPE_STRING: {
1726 MonoString *str = (MonoString*)val;
1727 /* there is no signature */
1728 len = str->length * 2;
1729 mono_metadata_encode_value (len, b, &b);
1730 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1732 char *swapped = g_malloc (2 * mono_string_length (str));
1733 const char *p = (const char*)mono_string_chars (str);
1735 swap_with_size (swapped, p, 2, mono_string_length (str));
1736 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1740 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1746 case MONO_TYPE_GENERICINST:
1747 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1750 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1753 /* there is no signature */
1754 mono_metadata_encode_value (len, b, &b);
1755 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1756 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1757 swap_with_size (blob_size, box_val, len, 1);
1758 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1760 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1768 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1773 sigbuffer_init (&buf, 32);
1775 sigbuffer_add_value (&buf, minfo->type);
1777 switch (minfo->type) {
1778 case MONO_NATIVE_BYVALTSTR:
1779 case MONO_NATIVE_BYVALARRAY:
1780 sigbuffer_add_value (&buf, minfo->count);
1782 case MONO_NATIVE_LPARRAY:
1783 if (minfo->eltype || minfo->has_size) {
1784 sigbuffer_add_value (&buf, minfo->eltype);
1785 if (minfo->has_size) {
1786 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1787 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1789 /* LAMESPEC: ElemMult is undocumented */
1790 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1794 case MONO_NATIVE_CUSTOM:
1796 str = mono_string_to_utf8 (minfo->guid);
1798 sigbuffer_add_value (&buf, len);
1799 sigbuffer_add_mem (&buf, str, len);
1802 sigbuffer_add_value (&buf, 0);
1804 /* native type name */
1805 sigbuffer_add_value (&buf, 0);
1806 /* custom marshaler type name */
1807 if (minfo->marshaltype || minfo->marshaltyperef) {
1808 if (minfo->marshaltyperef)
1809 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1811 str = mono_string_to_utf8 (minfo->marshaltype);
1813 sigbuffer_add_value (&buf, len);
1814 sigbuffer_add_mem (&buf, str, len);
1817 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1818 sigbuffer_add_value (&buf, 0);
1820 if (minfo->mcookie) {
1821 str = mono_string_to_utf8 (minfo->mcookie);
1823 sigbuffer_add_value (&buf, len);
1824 sigbuffer_add_mem (&buf, str, len);
1827 sigbuffer_add_value (&buf, 0);
1833 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1834 sigbuffer_free (&buf);
1839 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1841 MonoDynamicTable *table;
1844 /* maybe this fixup should be done in the C# code */
1845 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1846 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1847 table = &assembly->tables [MONO_TABLE_FIELD];
1848 fb->table_idx = table->next_idx ++;
1849 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1850 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1851 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1852 values [MONO_FIELD_FLAGS] = fb->attrs;
1853 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1855 if (fb->offset != -1) {
1856 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1858 alloc_table (table, table->rows);
1859 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1860 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1861 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1863 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1864 guint32 field_type = 0;
1865 table = &assembly->tables [MONO_TABLE_CONSTANT];
1867 alloc_table (table, table->rows);
1868 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1869 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1870 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1871 values [MONO_CONSTANT_TYPE] = field_type;
1872 values [MONO_CONSTANT_PADDING] = 0;
1874 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1876 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1878 alloc_table (table, table->rows);
1879 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1880 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1882 * We store it in the code section because it's simpler for now.
1885 if (mono_array_length (fb->rva_data) >= 10)
1886 stream_data_align (&assembly->code);
1887 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1889 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1890 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1892 if (fb->marshal_info) {
1893 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1895 alloc_table (table, table->rows);
1896 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1897 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1898 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1903 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1906 guint32 nparams = 0;
1907 MonoReflectionMethodBuilder *mb = fb->get_method;
1908 MonoReflectionMethodBuilder *smb = fb->set_method;
1911 if (mb && mb->parameters)
1912 nparams = mono_array_length (mb->parameters);
1913 if (!mb && smb && smb->parameters)
1914 nparams = mono_array_length (smb->parameters) - 1;
1915 sigbuffer_init (&buf, 32);
1916 sigbuffer_add_byte (&buf, 0x08);
1917 sigbuffer_add_value (&buf, nparams);
1919 encode_reflection_type (assembly, mb->rtype, &buf);
1920 for (i = 0; i < nparams; ++i) {
1921 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1922 encode_reflection_type (assembly, pt, &buf);
1924 } else if (smb && smb->parameters) {
1925 /* the property type is the last param */
1926 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1927 for (i = 0; i < nparams; ++i) {
1928 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1929 encode_reflection_type (assembly, pt, &buf);
1932 encode_reflection_type (assembly, fb->type, &buf);
1935 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1936 sigbuffer_free (&buf);
1941 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1943 MonoDynamicTable *table;
1945 guint num_methods = 0;
1949 * we need to set things in the following tables:
1950 * PROPERTYMAP (info already filled in _get_type_info ())
1951 * PROPERTY (rows already preallocated in _get_type_info ())
1952 * METHOD (method info already done with the generic method code)
1955 table = &assembly->tables [MONO_TABLE_PROPERTY];
1956 pb->table_idx = table->next_idx ++;
1957 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1958 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1959 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1960 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1962 /* FIXME: we still don't handle 'other' methods */
1963 if (pb->get_method) num_methods ++;
1964 if (pb->set_method) num_methods ++;
1966 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1967 table->rows += num_methods;
1968 alloc_table (table, table->rows);
1970 if (pb->get_method) {
1971 semaidx = table->next_idx ++;
1972 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1973 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1974 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1975 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1977 if (pb->set_method) {
1978 semaidx = table->next_idx ++;
1979 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1980 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1981 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1982 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1987 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1989 MonoDynamicTable *table;
1991 guint num_methods = 0;
1995 * we need to set things in the following tables:
1996 * EVENTMAP (info already filled in _get_type_info ())
1997 * EVENT (rows already preallocated in _get_type_info ())
1998 * METHOD (method info already done with the generic method code)
2001 table = &assembly->tables [MONO_TABLE_EVENT];
2002 eb->table_idx = table->next_idx ++;
2003 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2004 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2005 values [MONO_EVENT_FLAGS] = eb->attrs;
2006 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
2009 * FIXME: we still don't handle 'other' methods
2011 if (eb->add_method) num_methods ++;
2012 if (eb->remove_method) num_methods ++;
2013 if (eb->raise_method) num_methods ++;
2015 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2016 table->rows += num_methods;
2017 alloc_table (table, table->rows);
2019 if (eb->add_method) {
2020 semaidx = table->next_idx ++;
2021 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2022 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2023 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2024 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2026 if (eb->remove_method) {
2027 semaidx = table->next_idx ++;
2028 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2029 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2030 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2031 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2033 if (eb->raise_method) {
2034 semaidx = table->next_idx ++;
2035 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2036 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2037 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2038 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2043 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2045 MonoDynamicTable *table;
2046 guint32 num_constraints, i;
2050 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2051 num_constraints = gparam->iface_constraints ?
2052 mono_array_length (gparam->iface_constraints) : 0;
2053 table->rows += num_constraints;
2054 if (gparam->base_type)
2056 alloc_table (table, table->rows);
2058 if (gparam->base_type) {
2059 table_idx = table->next_idx ++;
2060 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2062 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2063 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2064 assembly, gparam->base_type->type);
2067 for (i = 0; i < num_constraints; i++) {
2068 MonoReflectionType *constraint = mono_array_get (
2069 gparam->iface_constraints, gpointer, i);
2071 table_idx = table->next_idx ++;
2072 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2074 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2075 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2076 assembly, constraint->type);
2081 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2083 GenericParamTableEntry *entry;
2086 * The GenericParam table must be sorted according to the `owner' field.
2087 * We need to do this sorting prior to writing the GenericParamConstraint
2088 * table, since we have to use the final GenericParam table indices there
2089 * and they must also be sorted.
2092 entry = g_new0 (GenericParamTableEntry, 1);
2093 entry->owner = owner;
2094 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2095 MOVING_GC_REGISTER (&entry->gparam);
2096 entry->gparam = gparam;
2098 g_ptr_array_add (assembly->gen_params, entry);
2102 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2104 MonoDynamicTable *table;
2105 MonoGenericParam *param;
2109 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2110 table_idx = table->next_idx ++;
2111 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2113 param = entry->gparam->type.type->data.generic_param;
2115 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2116 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2117 values [MONO_GENERICPARAM_NUMBER] = param->num;
2118 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2120 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2122 encode_constraints (entry->gparam, table_idx, assembly);
2126 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2128 MonoDynamicTable *table;
2131 guint32 cols [MONO_ASSEMBLY_SIZE];
2135 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2138 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2139 table = &assembly->tables [MONO_TABLE_MODULEREF];
2140 token = table->next_idx ++;
2142 alloc_table (table, table->rows);
2143 values = table->values + token * MONO_MODULEREF_SIZE;
2144 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2146 token <<= MONO_RESOLTION_SCOPE_BITS;
2147 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2148 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2153 if (image->assembly->dynamic)
2155 memset (cols, 0, sizeof (cols));
2157 /* image->assembly->image is the manifest module */
2158 image = image->assembly->image;
2159 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2162 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2163 token = table->next_idx ++;
2165 alloc_table (table, table->rows);
2166 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2167 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2168 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2169 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2170 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2171 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2172 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2173 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2174 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2176 if (strcmp ("", image->assembly->aname.culture)) {
2177 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2178 image->assembly->aname.culture);
2181 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2182 guchar pubtoken [9];
2184 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2185 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2187 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2189 token <<= MONO_RESOLTION_SCOPE_BITS;
2190 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2191 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2196 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2198 MonoDynamicTable *table;
2203 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2206 sigbuffer_init (&buf, 32);
2207 switch (type->type) {
2208 case MONO_TYPE_FNPTR:
2210 case MONO_TYPE_SZARRAY:
2211 case MONO_TYPE_ARRAY:
2213 case MONO_TYPE_MVAR:
2214 case MONO_TYPE_GENERICINST:
2215 encode_type (assembly, type, &buf);
2217 case MONO_TYPE_CLASS:
2218 case MONO_TYPE_VALUETYPE: {
2219 MonoClass *k = mono_class_from_mono_type (type);
2220 if (!k || !k->generic_container) {
2221 sigbuffer_free (&buf);
2224 encode_type (assembly, type, &buf);
2228 sigbuffer_free (&buf);
2232 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2233 if (assembly->save) {
2234 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2235 alloc_table (table, table->rows + 1);
2236 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2237 values [MONO_TYPESPEC_SIGNATURE] = token;
2239 sigbuffer_free (&buf);
2241 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2242 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2248 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2250 MonoDynamicTable *table;
2252 guint32 token, scope, enclosing;
2255 /* if the type requires a typespec, we must try that first*/
2256 if (try_typespec && (token = create_typespec (assembly, type)))
2258 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2261 klass = my_mono_class_from_mono_type (type);
2263 klass = mono_class_from_mono_type (type);
2266 * If it's in the same module and not a generic type parameter:
2268 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2269 (type->type != MONO_TYPE_MVAR)) {
2270 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2271 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2272 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2276 if (klass->nested_in) {
2277 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2278 /* get the typeref idx of the enclosing type */
2279 enclosing >>= MONO_TYPEDEFORREF_BITS;
2280 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2282 scope = resolution_scope_from_image (assembly, klass->image);
2284 table = &assembly->tables [MONO_TABLE_TYPEREF];
2285 if (assembly->save) {
2286 alloc_table (table, table->rows + 1);
2287 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2288 values [MONO_TYPEREF_SCOPE] = scope;
2289 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2290 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2292 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2293 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2295 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2300 * Despite the name, we handle also TypeSpec (with the above helper).
2303 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2305 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2309 * Insert a memberef row into the metadata: the token that point to the memberref
2310 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2311 * mono_image_get_fieldref_token()).
2312 * The sig param is an index to an already built signature.
2315 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2317 MonoDynamicTable *table;
2319 guint32 token, pclass;
2322 parent = mono_image_typedef_or_ref (assembly, type);
2323 switch (parent & MONO_TYPEDEFORREF_MASK) {
2324 case MONO_TYPEDEFORREF_TYPEREF:
2325 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2327 case MONO_TYPEDEFORREF_TYPESPEC:
2328 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2330 case MONO_TYPEDEFORREF_TYPEDEF:
2331 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2334 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2337 /* extract the index */
2338 parent >>= MONO_TYPEDEFORREF_BITS;
2340 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2342 if (assembly->save) {
2343 alloc_table (table, table->rows + 1);
2344 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2345 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2346 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2347 values [MONO_MEMBERREF_SIGNATURE] = sig;
2350 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2357 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2360 MonoMethodSignature *sig;
2362 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2364 if (create_typespec) {
2365 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2370 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2371 if (token && !create_typespec)
2374 g_assert (!method->is_inflated);
2377 * A methodref signature can't contain an unmanaged calling convention.
2379 sig = mono_metadata_signature_dup (mono_method_signature (method));
2380 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2381 sig->call_convention = MONO_CALL_DEFAULT;
2382 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2383 method->name, method_encode_signature (assembly, sig));
2385 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2388 if (create_typespec) {
2389 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2390 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2391 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2393 if (assembly->save) {
2396 alloc_table (table, table->rows + 1);
2397 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2398 values [MONO_METHODSPEC_METHOD] = token;
2399 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2402 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2404 /*methodspec and memberef tokens are diferent, */
2405 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2412 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2415 ReflectionMethodBuilder rmb;
2418 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2422 name = mono_string_to_utf8 (method->name);
2423 reflection_methodbuilder_from_method_builder (&rmb, method);
2426 * A methodref signature can't contain an unmanaged calling convention.
2427 * Since some flags are encoded as part of call_conv, we need to check against it.
2429 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2430 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2431 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2432 name, method_builder_encode_signature (assembly, &rmb));
2435 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2440 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2441 const gchar *name, guint32 sig)
2443 MonoDynamicTable *table;
2447 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2449 if (assembly->save) {
2450 alloc_table (table, table->rows + 1);
2451 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2452 values [MONO_MEMBERREF_CLASS] = original;
2453 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2454 values [MONO_MEMBERREF_SIGNATURE] = sig;
2457 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2464 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2468 guint32 nparams = mono_array_length (mb->generic_params);
2471 if (!assembly->save)
2474 sigbuffer_init (&buf, 32);
2476 sigbuffer_add_value (&buf, 0xa);
2477 sigbuffer_add_value (&buf, nparams);
2479 for (i = 0; i < nparams; i++) {
2480 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2481 sigbuffer_add_value (&buf, i);
2484 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2485 sigbuffer_free (&buf);
2490 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2492 MonoDynamicTable *table;
2494 guint32 token, mtoken = 0;
2496 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2500 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2502 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2503 switch (mono_metadata_token_table (mtoken)) {
2504 case MONO_TABLE_MEMBERREF:
2505 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2507 case MONO_TABLE_METHOD:
2508 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2511 g_assert_not_reached ();
2514 if (assembly->save) {
2515 alloc_table (table, table->rows + 1);
2516 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2517 values [MONO_METHODSPEC_METHOD] = mtoken;
2518 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2521 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2524 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2529 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2533 if (mb->generic_params && create_methodspec)
2534 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2536 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2540 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2541 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2546 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2549 ReflectionMethodBuilder rmb;
2552 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2556 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2558 name = mono_string_to_utf8 (rmb.name);
2559 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2560 name, method_builder_encode_signature (assembly, &rmb));
2563 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2568 is_field_on_inst (MonoClassField *field)
2570 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2574 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2577 get_field_on_inst_generic_type (MonoClassField *field)
2579 MonoDynamicGenericClass *dgclass;
2582 g_assert (is_field_on_inst (field));
2584 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2585 field_index = field - dgclass->fields;
2587 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2588 return dgclass->field_generic_types [field_index];
2592 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2596 MonoClassField *field;
2598 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2601 g_assert (f->field->parent);
2604 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2605 int index = field - field->parent->fields;
2606 type = field->parent->generic_class->container_class->fields [index].type;
2608 if (is_field_on_inst (f->field))
2609 type = get_field_on_inst_generic_type (f->field);
2611 type = f->field->type;
2613 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2614 mono_field_get_name (f->field),
2615 fieldref_encode_signature (assembly, type));
2616 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2621 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2625 MonoGenericClass *gclass;
2626 MonoDynamicGenericClass *dgclass;
2627 MonoReflectionFieldBuilder *fb = f->fb;
2630 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2633 klass = mono_class_from_mono_type (f->inst->type.type);
2634 gclass = f->inst->type.type->data.generic_class;
2635 g_assert (gclass->is_dynamic);
2636 dgclass = (MonoDynamicGenericClass *) gclass;
2638 name = mono_string_to_utf8 (fb->name);
2639 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2640 field_encode_signature (assembly, fb));
2642 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2647 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2651 MonoGenericClass *gclass;
2652 MonoDynamicGenericClass *dgclass;
2653 MonoReflectionCtorBuilder *cb = c->cb;
2654 ReflectionMethodBuilder rmb;
2657 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2659 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2662 klass = mono_class_from_mono_type (c->inst->type.type);
2663 gclass = c->inst->type.type->data.generic_class;
2664 g_assert (gclass->is_dynamic);
2665 dgclass = (MonoDynamicGenericClass *) gclass;
2667 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2669 name = mono_string_to_utf8 (rmb.name);
2671 sig = method_builder_encode_signature (assembly, &rmb);
2673 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2676 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2681 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2685 MonoGenericClass *gclass;
2686 MonoReflectionMethodBuilder *mb = m->mb;
2687 ReflectionMethodBuilder rmb;
2690 if (create_methodspec && mb->generic_params)
2692 g_assert_not_reached ();
2694 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2697 klass = mono_class_from_mono_type (m->inst->type.type);
2698 gclass = m->inst->type.type->data.generic_class;
2699 g_assert (gclass->is_dynamic);
2701 reflection_methodbuilder_from_method_builder (&rmb, mb);
2703 name = mono_string_to_utf8 (rmb.name);
2705 sig = method_builder_encode_signature (assembly, &rmb);
2707 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2710 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2715 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2719 guint32 nparams = context->method_inst->type_argc;
2722 if (!assembly->save)
2725 sigbuffer_init (&buf, 32);
2727 * FIXME: vararg, explicit_this, differenc call_conv values...
2729 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2730 sigbuffer_add_value (&buf, nparams);
2732 for (i = 0; i < nparams; i++)
2733 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2735 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2736 sigbuffer_free (&buf);
2741 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2743 MonoDynamicTable *table;
2745 guint32 token, mtoken = 0, sig;
2746 MonoMethodInflated *imethod;
2747 MonoMethod *declaring;
2749 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2751 g_assert (method->is_inflated);
2752 imethod = (MonoMethodInflated *) method;
2753 declaring = imethod->declaring;
2755 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2756 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2758 if (!mono_method_signature (declaring)->generic_param_count)
2761 switch (mono_metadata_token_table (mtoken)) {
2762 case MONO_TABLE_MEMBERREF:
2763 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2765 case MONO_TABLE_METHOD:
2766 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2769 g_assert_not_reached ();
2772 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2774 if (assembly->save) {
2775 alloc_table (table, table->rows + 1);
2776 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2777 values [MONO_METHODSPEC_METHOD] = mtoken;
2778 values [MONO_METHODSPEC_SIGNATURE] = sig;
2781 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2788 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2790 MonoMethodInflated *imethod;
2793 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2797 g_assert (method->is_inflated);
2798 imethod = (MonoMethodInflated *) method;
2800 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2801 token = method_encode_methodspec (assembly, method);
2803 guint32 sig = method_encode_signature (
2804 assembly, mono_method_signature (imethod->declaring));
2805 token = mono_image_get_memberref_token (
2806 assembly, &method->klass->byval_arg, method->name, sig);
2809 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2814 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2816 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2819 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2820 token = mono_image_get_memberref_token (
2821 assembly, &m->klass->byval_arg, m->name, sig);
2827 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2829 MonoDynamicTable *table;
2837 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2838 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2839 * Because of this, we must not insert it into the `typeref' hash table.
2842 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2846 sigbuffer_init (&buf, 32);
2848 g_assert (tb->generic_params);
2849 klass = mono_class_from_mono_type (tb->type.type);
2851 if (tb->generic_container)
2852 mono_reflection_create_generic_class (tb);
2854 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2855 g_assert (klass->generic_container);
2856 sigbuffer_add_value (&buf, klass->byval_arg.type);
2857 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2859 count = mono_array_length (tb->generic_params);
2860 sigbuffer_add_value (&buf, count);
2861 for (i = 0; i < count; i++) {
2862 MonoReflectionGenericParam *gparam;
2864 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2866 encode_type (assembly, gparam->type.type, &buf);
2869 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2871 if (assembly->save) {
2872 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2873 alloc_table (table, table->rows + 1);
2874 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2875 values [MONO_TYPESPEC_SIGNATURE] = token;
2877 sigbuffer_free (&buf);
2879 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2880 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2886 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2889 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2891 int i, count, len, pos;
2896 count += mono_array_length (modreq);
2898 count += mono_array_length (modopt);
2901 return mono_metadata_type_dup (NULL, type);
2903 len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
2905 memcpy (t, type, len);
2907 t->num_mods = count;
2910 for (i = 0; i < mono_array_length (modreq); ++i) {
2911 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
2912 t->modifiers [pos].required = 1;
2913 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2918 for (i = 0; i < mono_array_length (modopt); ++i) {
2919 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
2920 t->modifiers [pos].required = 0;
2921 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2930 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2932 MonoDynamicTable *table;
2934 MonoType *custom = NULL;
2936 guint32 token, pclass, parent, sig;
2939 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2943 klass = mono_class_from_mono_type (fb->typeb->type);
2944 name = mono_string_to_utf8 (fb->name);
2946 /* fb->type does not include the custom modifiers */
2947 /* FIXME: We should do this in one place when a fieldbuilder is created */
2948 if (fb->modreq || fb->modopt) {
2949 custom = add_custom_modifiers (assembly, fb->type->type, fb->modreq, fb->modopt);
2950 sig = fieldref_encode_signature (assembly, custom);
2953 sig = fieldref_encode_signature (assembly, fb->type->type);
2956 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2957 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2959 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2960 parent >>= MONO_TYPEDEFORREF_BITS;
2962 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2964 if (assembly->save) {
2965 alloc_table (table, table->rows + 1);
2966 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2967 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2968 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2969 values [MONO_MEMBERREF_SIGNATURE] = sig;
2972 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2974 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2980 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2987 if (!assembly->save)
2990 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2991 g_assert (helper->type == 2);
2993 if (helper->arguments)
2994 nargs = mono_array_length (helper->arguments);
2998 size = 10 + (nargs * 10);
3000 sigbuffer_init (&buf, 32);
3002 /* Encode calling convention */
3003 /* Change Any to Standard */
3004 if ((helper->call_conv & 0x03) == 0x03)
3005 helper->call_conv = 0x01;
3006 /* explicit_this implies has_this */
3007 if (helper->call_conv & 0x40)
3008 helper->call_conv &= 0x20;
3010 if (helper->call_conv == 0) { /* Unmanaged */
3011 idx = helper->unmanaged_call_conv - 1;
3014 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3015 if (helper->call_conv & 0x02) /* varargs */
3019 sigbuffer_add_byte (&buf, idx);
3020 sigbuffer_add_value (&buf, nargs);
3021 encode_reflection_type (assembly, helper->return_type, &buf);
3022 for (i = 0; i < nargs; ++i) {
3023 MonoArray *modreqs = NULL;
3024 MonoArray *modopts = NULL;
3025 MonoReflectionType *pt;
3027 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3028 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3029 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3030 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3032 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3033 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3034 encode_reflection_type (assembly, pt, &buf);
3036 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3037 sigbuffer_free (&buf);
3043 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3046 MonoDynamicTable *table;
3049 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3050 idx = table->next_idx ++;
3052 alloc_table (table, table->rows);
3053 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3055 values [MONO_STAND_ALONE_SIGNATURE] =
3056 mono_reflection_encode_sighelper (assembly, helper);
3062 reflection_cc_to_file (int call_conv) {
3063 switch (call_conv & 0x3) {
3065 case 1: return MONO_CALL_DEFAULT;
3066 case 2: return MONO_CALL_VARARG;
3068 g_assert_not_reached ();
3075 MonoMethodSignature *sig;
3081 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3086 MonoMethodSignature *sig;
3089 name = mono_string_to_utf8 (m->name);
3090 nparams = mono_array_length (m->parameters);
3091 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
3093 sig->sentinelpos = -1;
3094 sig->call_convention = reflection_cc_to_file (m->call_conv);
3095 sig->param_count = nparams;
3096 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
3097 for (i = 0; i < nparams; ++i) {
3098 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
3099 sig->params [i] = t->type;
3102 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3104 if (strcmp (name, am->name) == 0 &&
3105 mono_metadata_type_equal (am->parent, m->parent->type) &&
3106 mono_metadata_signature_equal (am->sig, sig)) {
3109 m->table_idx = am->token & 0xffffff;
3113 am = g_new0 (ArrayMethod, 1);
3116 am->parent = m->parent->type;
3117 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3118 method_encode_signature (assembly, sig));
3119 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3120 m->table_idx = am->token & 0xffffff;
3125 * Insert into the metadata tables all the info about the TypeBuilder tb.
3126 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3129 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3131 MonoDynamicTable *table;
3133 int i, is_object = 0, is_system = 0;
3136 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3137 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3138 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3139 n = mono_string_to_utf8 (tb->name);
3140 if (strcmp (n, "Object") == 0)
3142 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3144 n = mono_string_to_utf8 (tb->nspace);
3145 if (strcmp (n, "System") == 0)
3147 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3149 if (tb->parent && !(is_system && is_object) &&
3150 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3151 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
3153 values [MONO_TYPEDEF_EXTENDS] = 0;
3155 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3156 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3159 * if we have explicitlayout or sequentiallayouts, output data in the
3160 * ClassLayout table.
3162 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3163 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3164 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3166 alloc_table (table, table->rows);
3167 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3168 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3169 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3170 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3173 /* handle interfaces */
3174 if (tb->interfaces) {
3175 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3177 table->rows += mono_array_length (tb->interfaces);
3178 alloc_table (table, table->rows);
3179 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3180 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3181 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3182 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3183 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3184 values += MONO_INTERFACEIMPL_SIZE;
3190 table = &assembly->tables [MONO_TABLE_FIELD];
3191 table->rows += tb->num_fields;
3192 alloc_table (table, table->rows);
3193 for (i = 0; i < tb->num_fields; ++i)
3194 mono_image_get_field_info (
3195 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3198 /* handle constructors */
3200 table = &assembly->tables [MONO_TABLE_METHOD];
3201 table->rows += mono_array_length (tb->ctors);
3202 alloc_table (table, table->rows);
3203 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3204 mono_image_get_ctor_info (domain,
3205 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3208 /* handle methods */
3210 table = &assembly->tables [MONO_TABLE_METHOD];
3211 table->rows += tb->num_methods;
3212 alloc_table (table, table->rows);
3213 for (i = 0; i < tb->num_methods; ++i)
3214 mono_image_get_method_info (
3215 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3218 /* Do the same with properties etc.. */
3219 if (tb->events && mono_array_length (tb->events)) {
3220 table = &assembly->tables [MONO_TABLE_EVENT];
3221 table->rows += mono_array_length (tb->events);
3222 alloc_table (table, table->rows);
3223 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3225 alloc_table (table, table->rows);
3226 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3227 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3228 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3229 for (i = 0; i < mono_array_length (tb->events); ++i)
3230 mono_image_get_event_info (
3231 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3233 if (tb->properties && mono_array_length (tb->properties)) {
3234 table = &assembly->tables [MONO_TABLE_PROPERTY];
3235 table->rows += mono_array_length (tb->properties);
3236 alloc_table (table, table->rows);
3237 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3239 alloc_table (table, table->rows);
3240 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3241 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3242 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3243 for (i = 0; i < mono_array_length (tb->properties); ++i)
3244 mono_image_get_property_info (
3245 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3248 /* handle generic parameters */
3249 if (tb->generic_params) {
3250 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3251 table->rows += mono_array_length (tb->generic_params);
3252 alloc_table (table, table->rows);
3253 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3254 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3256 mono_image_get_generic_param_info (
3257 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3261 mono_image_add_decl_security (assembly,
3262 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3265 MonoDynamicTable *ntable;
3267 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3268 ntable->rows += mono_array_length (tb->subtypes);
3269 alloc_table (ntable, ntable->rows);
3270 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3272 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3273 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3275 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3276 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3277 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3278 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3279 mono_string_to_utf8 (tb->name), tb->table_idx,
3280 ntable->next_idx, ntable->rows);*/
3281 values += MONO_NESTED_CLASS_SIZE;
3288 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3292 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3294 if (!type->subtypes)
3297 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3298 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3299 collect_types (types, subtype);
3304 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3306 if ((*type1)->table_idx < (*type2)->table_idx)
3309 if ((*type1)->table_idx > (*type2)->table_idx)
3316 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3321 for (i = 0; i < mono_array_length (pinfo); ++i) {
3322 MonoReflectionParamBuilder *pb;
3323 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3326 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3331 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3334 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3336 for (i = 0; i < tb->num_fields; ++i) {
3337 MonoReflectionFieldBuilder* fb;
3338 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3339 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3343 for (i = 0; i < mono_array_length (tb->events); ++i) {
3344 MonoReflectionEventBuilder* eb;
3345 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3346 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3349 if (tb->properties) {
3350 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3351 MonoReflectionPropertyBuilder* pb;
3352 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3353 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3357 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3358 MonoReflectionCtorBuilder* cb;
3359 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3360 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3361 params_add_cattrs (assembly, cb->pinfo);
3366 for (i = 0; i < tb->num_methods; ++i) {
3367 MonoReflectionMethodBuilder* mb;
3368 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3369 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3370 params_add_cattrs (assembly, mb->pinfo);
3375 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3376 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3381 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3385 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3387 if (moduleb->global_methods) {
3388 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3389 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3390 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3391 params_add_cattrs (assembly, mb->pinfo);
3395 if (moduleb->global_fields) {
3396 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3397 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3398 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3402 if (moduleb->types) {
3403 for (i = 0; i < moduleb->num_types; ++i)
3404 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3409 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3411 MonoDynamicTable *table;
3415 char *b = blob_size;
3418 table = &assembly->tables [MONO_TABLE_FILE];
3420 alloc_table (table, table->rows);
3421 values = table->values + table->next_idx * MONO_FILE_SIZE;
3422 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3423 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3424 if (module->image->dynamic) {
3425 /* This depends on the fact that the main module is emitted last */
3426 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3427 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3430 path = g_strdup (module->image->name);
3432 mono_sha1_get_digest_from_file (path, hash);
3435 mono_metadata_encode_value (20, b, &b);
3436 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3437 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3442 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3444 MonoDynamicTable *table;
3447 table = &assembly->tables [MONO_TABLE_MODULE];
3448 mb->table_idx = table->next_idx ++;
3449 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3450 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3453 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3454 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3455 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3456 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3460 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3461 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3463 MonoDynamicTable *table;
3467 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3468 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3471 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3473 alloc_table (table, table->rows);
3474 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3476 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3477 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3478 if (klass->nested_in)
3479 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3481 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3482 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3483 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3485 res = table->next_idx;
3489 /* Emit nested types */
3490 if (klass->nested_classes) {
3493 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3494 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3501 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3502 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3507 klass = mono_class_from_mono_type (tb->type.type);
3509 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3511 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3512 parent_index, assembly);
3516 * We need to do this ourselves since klass->nested_classes is not set up.
3519 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3520 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3525 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3526 guint32 module_index, MonoDynamicImage *assembly)
3528 MonoImage *image = module->image;
3532 t = &image->tables [MONO_TABLE_TYPEDEF];
3534 for (i = 0; i < t->rows; ++i) {
3535 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3537 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3538 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3543 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3545 MonoDynamicTable *table;
3551 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3553 if (assemblyb->type_forwarders) {
3554 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3555 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3561 klass = mono_class_from_mono_type (t->type);
3563 scope = resolution_scope_from_image (assembly, klass->image);
3564 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3565 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3568 alloc_table (table, table->rows);
3569 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3571 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3572 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3573 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3574 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3575 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3582 #define align_pointer(base,p)\
3584 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3586 (p) += 4 - (__diff & 3);\
3590 compare_constants (const void *a, const void *b)
3592 const guint32 *a_values = a;
3593 const guint32 *b_values = b;
3594 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3598 compare_semantics (const void *a, const void *b)
3600 const guint32 *a_values = a;
3601 const guint32 *b_values = b;
3602 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3605 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3609 compare_custom_attrs (const void *a, const void *b)
3611 const guint32 *a_values = a;
3612 const guint32 *b_values = b;
3614 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3618 compare_field_marshal (const void *a, const void *b)
3620 const guint32 *a_values = a;
3621 const guint32 *b_values = b;
3623 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3627 compare_nested (const void *a, const void *b)
3629 const guint32 *a_values = a;
3630 const guint32 *b_values = b;
3632 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3636 compare_genericparam (const void *a, const void *b)
3638 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3639 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3641 if ((*b_entry)->owner == (*a_entry)->owner)
3643 (*a_entry)->gparam->type.type->data.generic_param->num -
3644 (*b_entry)->gparam->type.type->data.generic_param->num;
3646 return (*a_entry)->owner - (*b_entry)->owner;
3650 compare_declsecurity_attrs (const void *a, const void *b)
3652 const guint32 *a_values = a;
3653 const guint32 *b_values = b;
3655 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3659 compare_interface_impl (const void *a, const void *b)
3661 const guint32 *a_values = a;
3662 const guint32 *b_values = b;
3664 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3668 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3672 pad_heap (MonoDynamicStream *sh)
3674 if (sh->index & 3) {
3675 int sz = 4 - (sh->index & 3);
3676 memset (sh->data + sh->index, 0, sz);
3683 MonoDynamicStream *stream;
3687 * build_compressed_metadata() fills in the blob of data that represents the
3688 * raw metadata as it will be saved in the PE file. The five streams are output
3689 * and the metadata tables are comnpressed from the guint32 array representation,
3690 * to the compressed on-disk format.
3693 build_compressed_metadata (MonoDynamicImage *assembly)
3695 MonoDynamicTable *table;
3697 guint64 valid_mask = 0;
3698 guint64 sorted_mask;
3699 guint32 heapt_size = 0;
3700 guint32 meta_size = 256; /* allow for header and other stuff */
3701 guint32 table_offset;
3702 guint32 ntables = 0;
3708 struct StreamDesc stream_desc [5];
3710 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3711 for (i = 0; i < assembly->gen_params->len; i++){
3712 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3713 write_generic_param_entry (assembly, entry);
3716 stream_desc [0].name = "#~";
3717 stream_desc [0].stream = &assembly->tstream;
3718 stream_desc [1].name = "#Strings";
3719 stream_desc [1].stream = &assembly->sheap;
3720 stream_desc [2].name = "#US";
3721 stream_desc [2].stream = &assembly->us;
3722 stream_desc [3].name = "#Blob";
3723 stream_desc [3].stream = &assembly->blob;
3724 stream_desc [4].name = "#GUID";
3725 stream_desc [4].stream = &assembly->guid;
3727 /* tables that are sorted */
3728 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3729 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3730 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3731 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3732 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3733 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3734 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3736 /* Compute table sizes */
3737 /* the MonoImage has already been created in mono_image_basic_init() */
3738 meta = &assembly->image;
3740 /* sizes should be multiple of 4 */
3741 pad_heap (&assembly->blob);
3742 pad_heap (&assembly->guid);
3743 pad_heap (&assembly->sheap);
3744 pad_heap (&assembly->us);
3746 /* Setup the info used by compute_sizes () */
3747 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3748 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3749 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3751 meta_size += assembly->blob.index;
3752 meta_size += assembly->guid.index;
3753 meta_size += assembly->sheap.index;
3754 meta_size += assembly->us.index;
3756 for (i=0; i < MONO_TABLE_NUM; ++i)
3757 meta->tables [i].rows = assembly->tables [i].rows;
3759 for (i = 0; i < MONO_TABLE_NUM; i++){
3760 if (meta->tables [i].rows == 0)
3762 valid_mask |= (guint64)1 << i;
3764 meta->tables [i].row_size = mono_metadata_compute_size (
3765 meta, i, &meta->tables [i].size_bitfield);
3766 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3768 heapt_size += 24; /* #~ header size */
3769 heapt_size += ntables * 4;
3770 /* make multiple of 4 */
3773 meta_size += heapt_size;
3774 meta->raw_metadata = g_malloc0 (meta_size);
3775 p = (unsigned char*)meta->raw_metadata;
3776 /* the metadata signature */
3777 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3778 /* version numbers and 4 bytes reserved */
3779 int16val = (guint16*)p;
3780 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3781 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3783 /* version string */
3784 int32val = (guint32*)p;
3785 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3787 memcpy (p, meta->version, strlen (meta->version));
3788 p += GUINT32_FROM_LE (*int32val);
3789 align_pointer (meta->raw_metadata, p);
3790 int16val = (guint16*)p;
3791 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3792 *int16val = GUINT16_TO_LE (5); /* number of streams */
3796 * write the stream info.
3798 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3799 table_offset += 3; table_offset &= ~3;
3801 assembly->tstream.index = heapt_size;
3802 for (i = 0; i < 5; ++i) {
3803 int32val = (guint32*)p;
3804 stream_desc [i].stream->offset = table_offset;
3805 *int32val++ = GUINT32_TO_LE (table_offset);
3806 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3807 table_offset += GUINT32_FROM_LE (*int32val);
3808 table_offset += 3; table_offset &= ~3;
3810 strcpy ((char*)p, stream_desc [i].name);
3811 p += strlen (stream_desc [i].name) + 1;
3812 align_pointer (meta->raw_metadata, p);
3815 * now copy the data, the table stream header and contents goes first.
3817 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3818 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3819 int32val = (guint32*)p;
3820 *int32val = GUINT32_TO_LE (0); /* reserved */
3823 if (mono_framework_version () > 1) {
3824 *p++ = 2; /* version */
3827 *p++ = 1; /* version */
3831 if (meta->idx_string_wide)
3833 if (meta->idx_guid_wide)
3835 if (meta->idx_blob_wide)
3838 *p++ = 1; /* reserved */
3839 int64val = (guint64*)p;
3840 *int64val++ = GUINT64_TO_LE (valid_mask);
3841 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3843 int32val = (guint32*)p;
3844 for (i = 0; i < MONO_TABLE_NUM; i++){
3845 if (meta->tables [i].rows == 0)
3847 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3849 p = (unsigned char*)int32val;
3851 /* sort the tables that still need sorting */
3852 table = &assembly->tables [MONO_TABLE_CONSTANT];
3854 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3855 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3857 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3858 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3860 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3861 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3863 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3864 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3866 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3867 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3868 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3870 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3871 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3873 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3875 /* compress the tables */
3876 for (i = 0; i < MONO_TABLE_NUM; i++){
3879 guint32 bitfield = meta->tables [i].size_bitfield;
3880 if (!meta->tables [i].rows)
3882 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3883 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3884 meta->tables [i].base = (char*)p;
3885 for (row = 1; row <= meta->tables [i].rows; ++row) {
3886 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3887 for (col = 0; col < assembly->tables [i].columns; ++col) {
3888 switch (mono_metadata_table_size (bitfield, col)) {
3890 *p++ = values [col];
3893 *p++ = values [col] & 0xff;
3894 *p++ = (values [col] >> 8) & 0xff;
3897 *p++ = values [col] & 0xff;
3898 *p++ = (values [col] >> 8) & 0xff;
3899 *p++ = (values [col] >> 16) & 0xff;
3900 *p++ = (values [col] >> 24) & 0xff;
3903 g_assert_not_reached ();
3907 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3910 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3911 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3912 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3913 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3914 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3916 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3920 * Some tables in metadata need to be sorted according to some criteria, but
3921 * when methods and fields are first created with reflection, they may be assigned a token
3922 * that doesn't correspond to the final token they will get assigned after the sorting.
3923 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3924 * with the reflection objects that represent them. Once all the tables are set up, the
3925 * reflection objects will contains the correct table index. fixup_method() will fixup the
3926 * tokens for the method with ILGenerator @ilgen.
3929 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3931 guint32 code_idx = GPOINTER_TO_UINT (value);
3932 MonoReflectionILTokenInfo *iltoken;
3933 MonoReflectionFieldBuilder *field;
3934 MonoReflectionCtorBuilder *ctor;
3935 MonoReflectionMethodBuilder *method;
3936 MonoReflectionTypeBuilder *tb;
3937 MonoReflectionArrayMethod *am;
3939 unsigned char *target;
3941 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3942 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3943 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3944 switch (target [3]) {
3945 case MONO_TABLE_FIELD:
3946 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3947 field = (MonoReflectionFieldBuilder *)iltoken->member;
3948 idx = field->table_idx;
3949 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3950 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3951 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3953 g_assert_not_reached ();
3956 case MONO_TABLE_METHOD:
3957 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3958 method = (MonoReflectionMethodBuilder *)iltoken->member;
3959 idx = method->table_idx;
3960 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3961 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3962 idx = ctor->table_idx;
3963 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3964 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3965 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3966 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3968 g_assert_not_reached ();
3971 case MONO_TABLE_TYPEDEF:
3972 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3973 g_assert_not_reached ();
3974 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3975 idx = tb->table_idx;
3977 case MONO_TABLE_MEMBERREF:
3978 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3979 am = (MonoReflectionArrayMethod*)iltoken->member;
3980 idx = am->table_idx;
3981 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3982 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3983 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3984 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3985 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3986 g_assert (m->klass->generic_class || m->klass->generic_container);
3988 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3990 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3991 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3992 g_assert (is_field_on_inst (f));
3994 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3995 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3997 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3999 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4001 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4004 g_assert_not_reached ();
4007 case MONO_TABLE_METHODSPEC:
4008 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4009 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4010 g_assert (mono_method_signature (m)->generic_param_count);
4012 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4015 g_assert_not_reached ();
4019 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4021 target [0] = idx & 0xff;
4022 target [1] = (idx >> 8) & 0xff;
4023 target [2] = (idx >> 16) & 0xff;
4030 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4031 * value is not known when the table is emitted.
4034 fixup_cattrs (MonoDynamicImage *assembly)
4036 MonoDynamicTable *table;
4038 guint32 type, i, idx, token;
4041 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4043 for (i = 0; i < table->rows; ++i) {
4044 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4046 type = values [MONO_CUSTOM_ATTR_TYPE];
4047 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4048 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4049 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4050 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4053 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4054 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4055 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4056 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4063 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4065 MonoDynamicTable *table;
4068 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4070 alloc_table (table, table->rows);
4071 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4072 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4073 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4074 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4075 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4080 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4082 MonoDynamicTable *table;
4086 char *b = blob_size;
4088 guint32 idx, offset;
4090 if (rsrc->filename) {
4091 name = mono_string_to_utf8 (rsrc->filename);
4092 sname = g_path_get_basename (name);
4094 table = &assembly->tables [MONO_TABLE_FILE];
4096 alloc_table (table, table->rows);
4097 values = table->values + table->next_idx * MONO_FILE_SIZE;
4098 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4099 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4102 mono_sha1_get_digest_from_file (name, hash);
4103 mono_metadata_encode_value (20, b, &b);
4104 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4105 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4107 idx = table->next_idx++;
4109 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4115 data = mono_array_addr (rsrc->data, char, 0);
4116 len = mono_array_length (rsrc->data);
4122 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4123 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4124 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4125 mono_image_add_stream_data (&assembly->resources, data, len);
4129 * The entry should be emitted into the MANIFESTRESOURCE table of
4130 * the main module, but that needs to reference the FILE table
4131 * which isn't emitted yet.
4138 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4142 set_version_from_string (MonoString *version, guint32 *values)
4144 gchar *ver, *p, *str;
4147 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4148 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4149 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4150 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4153 ver = str = mono_string_to_utf8 (version);
4154 for (i = 0; i < 4; ++i) {
4155 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4161 /* handle Revision and Build */
4171 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4175 char *b = blob_size;
4180 len = mono_array_length (pkey);
4181 mono_metadata_encode_value (len, b, &b);
4182 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4183 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4185 assembly->public_key = g_malloc (len);
4186 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4187 assembly->public_key_len = len;
4189 /* Special case: check for ECMA key (16 bytes) */
4190 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4191 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4192 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4193 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4194 /* minimum key size (in 2.0) is 384 bits */
4195 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4197 /* FIXME - verifier */
4198 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4199 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4201 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4207 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4209 MonoDynamicTable *table;
4210 MonoDynamicImage *assembly;
4211 MonoReflectionAssemblyBuilder *assemblyb;
4215 guint32 module_index;
4217 assemblyb = moduleb->assemblyb;
4218 assembly = moduleb->dynamic_image;
4219 domain = mono_object_domain (assemblyb);
4221 /* Emit ASSEMBLY table */
4222 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4223 alloc_table (table, 1);
4224 values = table->values + MONO_ASSEMBLY_SIZE;
4225 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4226 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4227 if (assemblyb->culture) {
4228 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4230 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4232 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4233 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4234 set_version_from_string (assemblyb->version, values);
4236 /* Emit FILE + EXPORTED_TYPE table */
4238 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4240 MonoReflectionModuleBuilder *file_module =
4241 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4242 if (file_module != moduleb) {
4243 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4245 if (file_module->types) {
4246 for (j = 0; j < file_module->num_types; ++j) {
4247 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4248 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4253 if (assemblyb->loaded_modules) {
4254 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4255 MonoReflectionModule *file_module =
4256 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4257 mono_image_fill_file_table (domain, file_module, assembly);
4259 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4262 if (assemblyb->type_forwarders)
4263 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4265 /* Emit MANIFESTRESOURCE table */
4267 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4269 MonoReflectionModuleBuilder *file_module =
4270 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4271 /* The table for the main module is emitted later */
4272 if (file_module != moduleb) {
4274 if (file_module->resources) {
4275 int len = mono_array_length (file_module->resources);
4276 for (j = 0; j < len; ++j) {
4277 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4278 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4285 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4288 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4289 * for the modulebuilder @moduleb.
4290 * At the end of the process, method and field tokens are fixed up and the
4291 * on-disk compressed metadata representation is created.
4294 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4296 MonoDynamicTable *table;
4297 MonoDynamicImage *assembly;
4298 MonoReflectionAssemblyBuilder *assemblyb;
4304 assemblyb = moduleb->assemblyb;
4305 assembly = moduleb->dynamic_image;
4306 domain = mono_object_domain (assemblyb);
4308 if (assembly->text_rva)
4311 assembly->text_rva = START_TEXT_RVA;
4313 if (moduleb->is_main) {
4314 mono_image_emit_manifest (moduleb);
4317 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4318 table->rows = 1; /* .<Module> */
4320 alloc_table (table, table->rows);
4322 * Set the first entry.
4324 values = table->values + table->columns;
4325 values [MONO_TYPEDEF_FLAGS] = 0;
4326 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4327 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4328 values [MONO_TYPEDEF_EXTENDS] = 0;
4329 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4330 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4333 * handle global methods
4334 * FIXME: test what to do when global methods are defined in multiple modules.
4336 if (moduleb->global_methods) {
4337 table = &assembly->tables [MONO_TABLE_METHOD];
4338 table->rows += mono_array_length (moduleb->global_methods);
4339 alloc_table (table, table->rows);
4340 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4341 mono_image_get_method_info (
4342 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4344 if (moduleb->global_fields) {
4345 table = &assembly->tables [MONO_TABLE_FIELD];
4346 table->rows += mono_array_length (moduleb->global_fields);
4347 alloc_table (table, table->rows);
4348 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4349 mono_image_get_field_info (
4350 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4353 table = &assembly->tables [MONO_TABLE_MODULE];
4354 alloc_table (table, 1);
4355 mono_image_fill_module_table (domain, moduleb, assembly);
4357 /* Collect all types into a list sorted by their table_idx */
4358 types = g_ptr_array_new ();
4361 for (i = 0; i < moduleb->num_types; ++i) {
4362 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4363 collect_types (types, type);
4366 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4367 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4368 table->rows += types->len;
4369 alloc_table (table, table->rows);
4372 * Emit type names + namespaces at one place inside the string heap,
4373 * so load_class_names () needs to touch fewer pages.
4375 for (i = 0; i < types->len; ++i) {
4376 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4377 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
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->name);
4384 for (i = 0; i < types->len; ++i) {
4385 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4386 mono_image_get_type_info (domain, type, assembly);
4390 * table->rows is already set above and in mono_image_fill_module_table.
4392 /* add all the custom attributes at the end, once all the indexes are stable */
4393 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4395 /* CAS assembly permissions */
4396 if (assemblyb->permissions_minimum)
4397 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4398 if (assemblyb->permissions_optional)
4399 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4400 if (assemblyb->permissions_refused)
4401 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4403 module_add_cattrs (assembly, moduleb);
4406 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4408 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4409 * the final tokens and don't need another fixup pass. */
4411 if (moduleb->global_methods) {
4412 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4413 MonoReflectionMethodBuilder *mb = mono_array_get (
4414 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4415 mono_image_add_methodimpl (assembly, mb);
4419 for (i = 0; i < types->len; ++i) {
4420 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4421 if (type->methods) {
4422 for (j = 0; j < type->num_methods; ++j) {
4423 MonoReflectionMethodBuilder *mb = mono_array_get (
4424 type->methods, MonoReflectionMethodBuilder*, j);
4426 mono_image_add_methodimpl (assembly, mb);
4431 g_ptr_array_free (types, TRUE);
4433 fixup_cattrs (assembly);
4436 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4439 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4441 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4444 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4446 #ifndef DISABLE_REFLECTION_EMIT
4449 * mono_image_insert_string:
4450 * @module: module builder object
4453 * Insert @str into the user string stream of @module.
4456 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4458 MonoDynamicImage *assembly;
4463 MONO_ARCH_SAVE_REGS;
4465 if (!module->dynamic_image)
4466 mono_image_module_basic_init (module);
4468 assembly = module->dynamic_image;
4470 if (assembly->save) {
4471 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4472 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4473 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4475 char *swapped = g_malloc (2 * mono_string_length (str));
4476 const char *p = (const char*)mono_string_chars (str);
4478 swap_with_size (swapped, p, 2, mono_string_length (str));
4479 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4483 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4485 mono_image_add_stream_data (&assembly->us, "", 1);
4487 idx = assembly->us.index ++;
4490 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4492 return MONO_TOKEN_STRING | idx;
4496 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4501 klass = obj->vtable->klass;
4502 if (strcmp (klass->name, "MonoMethod") == 0) {
4503 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4504 MonoMethodSignature *sig, *old;
4505 guint32 sig_token, parent;
4508 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4510 nargs = mono_array_length (opt_param_types);
4511 old = mono_method_signature (method);
4512 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4514 sig->hasthis = old->hasthis;
4515 sig->explicit_this = old->explicit_this;
4516 sig->call_convention = old->call_convention;
4517 sig->generic_param_count = old->generic_param_count;
4518 sig->param_count = old->param_count + nargs;
4519 sig->sentinelpos = old->param_count;
4520 sig->ret = old->ret;
4522 for (i = 0; i < old->param_count; i++)
4523 sig->params [i] = old->params [i];
4525 for (i = 0; i < nargs; i++) {
4526 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4527 sig->params [old->param_count + i] = rt->type;
4530 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4531 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4532 parent >>= MONO_TYPEDEFORREF_BITS;
4534 parent <<= MONO_MEMBERREF_PARENT_BITS;
4535 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4537 sig_token = method_encode_signature (assembly, sig);
4538 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4539 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4540 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4541 ReflectionMethodBuilder rmb;
4542 guint32 parent, sig;
4545 reflection_methodbuilder_from_method_builder (&rmb, mb);
4546 rmb.opt_types = opt_param_types;
4548 sig = method_builder_encode_signature (assembly, &rmb);
4550 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4551 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4553 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4554 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4556 name = mono_string_to_utf8 (rmb.name);
4557 token = mono_image_get_varargs_method_token (
4558 assembly, parent, name, sig);
4561 g_error ("requested method token for %s\n", klass->name);
4568 * mono_image_create_token:
4569 * @assembly: a dynamic assembly
4571 * @register_token: Whenever to register the token in the assembly->tokens hash.
4573 * Get a token to insert in the IL code stream for the given MemberInfo.
4574 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4575 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4579 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4580 gboolean create_methodspec, gboolean register_token)
4585 klass = obj->vtable->klass;
4586 if (strcmp (klass->name, "MethodBuilder") == 0) {
4587 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4588 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4590 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4591 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4593 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4594 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4595 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4596 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4597 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4599 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4600 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4602 token = mono_image_get_ctorbuilder_token (assembly, mb);
4603 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4604 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4605 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4606 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4607 if (tb->generic_params) {
4608 token = mono_image_get_generic_field_token (assembly, fb);
4610 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4612 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4613 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4614 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4615 } else if (strcmp (klass->name, "MonoType") == 0) {
4616 MonoReflectionType *tb = (MonoReflectionType *)obj;
4617 MonoClass *mc = mono_class_from_mono_type (tb->type);
4618 token = mono_metadata_token_from_dor (
4619 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4620 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4621 MonoReflectionType *tb = (MonoReflectionType *)obj;
4622 token = mono_metadata_token_from_dor (
4623 mono_image_typedef_or_ref (assembly, tb->type));
4624 } else if (strcmp (klass->name, "MonoGenericClass") == 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, "MonoCMethod") == 0 ||
4629 strcmp (klass->name, "MonoMethod") == 0 ||
4630 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4631 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4632 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4633 if (m->method->is_inflated) {
4634 if (create_methodspec)
4635 token = mono_image_get_methodspec_token (assembly, m->method);
4637 token = mono_image_get_inflated_method_token (assembly, m->method);
4638 } else if ((m->method->klass->image == &assembly->image) &&
4639 !m->method->klass->generic_class) {
4640 static guint32 method_table_idx = 0xffffff;
4641 if (m->method->klass->wastypebuilder) {
4642 /* we use the same token as the one that was assigned
4643 * to the Methodbuilder.
4644 * FIXME: do the equivalent for Fields.
4646 token = m->method->token;
4649 * Each token should have a unique index, but the indexes are
4650 * assigned by managed code, so we don't know about them. An
4651 * easy solution is to count backwards...
4653 method_table_idx --;
4654 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4657 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4659 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4660 } else if (strcmp (klass->name, "MonoField") == 0) {
4661 MonoReflectionField *f = (MonoReflectionField *)obj;
4662 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4663 static guint32 field_table_idx = 0xffffff;
4665 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4667 token = mono_image_get_fieldref_token (assembly, f);
4669 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4670 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4671 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4672 token = mono_image_get_array_token (assembly, m);
4673 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4674 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4675 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4676 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4677 MonoReflectionType *tb = (MonoReflectionType *)obj;
4678 token = mono_metadata_token_from_dor (
4679 mono_image_typedef_or_ref (assembly, tb->type));
4680 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4681 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4682 token = mono_image_get_field_on_inst_token (assembly, f);
4683 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4684 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4685 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4686 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4687 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4688 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4690 g_error ("requested token for %s\n", klass->name);
4694 mono_image_register_token (assembly, token, obj);
4700 * mono_image_register_token:
4702 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4703 * the Module.ResolveXXXToken () methods to work.
4706 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4708 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4710 /* There could be multiple MethodInfo objects with the same token */
4711 //g_assert (prev == obj);
4713 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4717 #endif /* DISABLE_REFLECTION_EMIT */
4720 guint32 import_lookup_table;
4724 guint32 import_address_table_rva;
4732 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4734 static MonoDynamicImage*
4735 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4737 static const guchar entrycode [16] = {0xff, 0x25, 0};
4738 MonoDynamicImage *image;
4741 const char *version;
4743 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4744 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4746 version = mono_get_runtime_info ()->runtime_version;
4749 image = GC_MALLOC (sizeof (MonoDynamicImage));
4751 image = g_new0 (MonoDynamicImage, 1);
4754 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4756 /*g_print ("created image %p\n", image);*/
4757 /* keep in sync with image.c */
4758 image->image.name = assembly_name;
4759 image->image.assembly_name = image->image.name; /* they may be different */
4760 image->image.module_name = module_name;
4761 image->image.version = g_strdup (version);
4762 image->image.md_version_major = 1;
4763 image->image.md_version_minor = 1;
4764 image->image.dynamic = TRUE;
4766 image->image.references = g_new0 (MonoAssembly*, 1);
4767 image->image.references [0] = NULL;
4769 mono_image_init (&image->image);
4771 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4772 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4773 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4774 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4775 image->handleref = g_hash_table_new (NULL, NULL);
4776 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4777 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4778 image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4779 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4780 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4781 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4782 image->gen_params = g_ptr_array_new ();
4784 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4785 string_heap_init (&image->sheap);
4786 mono_image_add_stream_data (&image->us, "", 1);
4787 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4788 /* import tables... */
4789 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4790 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4791 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4792 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4793 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4794 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4795 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4796 stream_data_align (&image->code);
4798 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4800 for (i=0; i < MONO_TABLE_NUM; ++i) {
4801 image->tables [i].next_idx = 1;
4802 image->tables [i].columns = table_sizes [i];
4805 image->image.assembly = (MonoAssembly*)assembly;
4806 image->run = assembly->run;
4807 image->save = assembly->save;
4808 image->pe_kind = 0x1; /* ILOnly */
4809 image->machine = 0x14c; /* I386 */
4811 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4817 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4823 mono_dynamic_image_free (MonoDynamicImage *image)
4825 MonoDynamicImage *di = image;
4830 mono_g_hash_table_destroy (di->methodspec);
4832 g_hash_table_destroy (di->typespec);
4834 g_hash_table_destroy (di->typeref);
4836 g_hash_table_destroy (di->handleref);
4838 mono_g_hash_table_destroy (di->tokens);
4839 if (di->generic_def_objects)
4840 mono_g_hash_table_destroy (di->generic_def_objects);
4841 if (di->blob_cache) {
4842 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4843 g_hash_table_destroy (di->blob_cache);
4845 if (di->standalonesig_cache)
4846 g_hash_table_destroy (di->standalonesig_cache);
4847 for (list = di->array_methods; list; list = list->next) {
4848 ArrayMethod *am = (ArrayMethod *)list->data;
4853 g_list_free (di->array_methods);
4854 if (di->gen_params) {
4855 for (i = 0; i < di->gen_params->len; i++) {
4856 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4857 if (entry->gparam->type.type) {
4858 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4859 g_free ((char*)param->name);
4864 g_ptr_array_free (di->gen_params, TRUE);
4866 if (di->token_fixups)
4867 mono_g_hash_table_destroy (di->token_fixups);
4868 if (di->method_to_table_idx)
4869 g_hash_table_destroy (di->method_to_table_idx);
4870 if (di->field_to_table_idx)
4871 g_hash_table_destroy (di->field_to_table_idx);
4872 if (di->method_aux_hash)
4873 g_hash_table_destroy (di->method_aux_hash);
4874 g_free (di->strong_name);
4875 g_free (di->win32_res);
4877 g_free (di->public_key);
4879 /*g_print ("string heap destroy for image %p\n", di);*/
4880 mono_dynamic_stream_reset (&di->sheap);
4881 mono_dynamic_stream_reset (&di->code);
4882 mono_dynamic_stream_reset (&di->resources);
4883 mono_dynamic_stream_reset (&di->us);
4884 mono_dynamic_stream_reset (&di->blob);
4885 mono_dynamic_stream_reset (&di->tstream);
4886 mono_dynamic_stream_reset (&di->guid);
4887 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4888 g_free (di->tables [i].values);
4892 #ifndef DISABLE_REFLECTION_EMIT
4895 * mono_image_basic_init:
4896 * @assembly: an assembly builder object
4898 * Create the MonoImage that represents the assembly builder and setup some
4899 * of the helper hash table and the basic metadata streams.
4902 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4904 MonoDynamicAssembly *assembly;
4905 MonoDynamicImage *image;
4906 MonoDomain *domain = mono_object_domain (assemblyb);
4908 MONO_ARCH_SAVE_REGS;
4910 if (assemblyb->dynamic_assembly)
4914 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4916 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4919 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4921 assembly->assembly.ref_count = 1;
4922 assembly->assembly.dynamic = TRUE;
4923 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4924 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4925 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4926 if (assemblyb->culture)
4927 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4929 assembly->assembly.aname.culture = g_strdup ("");
4931 if (assemblyb->version) {
4932 char *vstr = mono_string_to_utf8 (assemblyb->version);
4933 char **version = g_strsplit (vstr, ".", 4);
4934 char **parts = version;
4935 assembly->assembly.aname.major = atoi (*parts++);
4936 assembly->assembly.aname.minor = atoi (*parts++);
4937 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4938 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4940 g_strfreev (version);
4943 assembly->assembly.aname.major = 0;
4944 assembly->assembly.aname.minor = 0;
4945 assembly->assembly.aname.build = 0;
4946 assembly->assembly.aname.revision = 0;
4949 assembly->run = assemblyb->access != 2;
4950 assembly->save = assemblyb->access != 1;
4952 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4953 image->initial_image = TRUE;
4954 assembly->assembly.aname.name = image->image.name;
4955 assembly->assembly.image = &image->image;
4957 mono_domain_assemblies_lock (domain);
4958 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4959 mono_domain_assemblies_unlock (domain);
4961 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4963 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4965 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4968 #endif /* DISABLE_REFLECTION_EMIT */
4971 calc_section_size (MonoDynamicImage *assembly)
4975 /* alignment constraints */
4976 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4977 g_assert ((assembly->code.index % 4) == 0);
4978 assembly->meta_size += 3;
4979 assembly->meta_size &= ~3;
4980 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4981 g_assert ((assembly->resources.index % 4) == 0);
4983 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4984 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4987 if (assembly->win32_res) {
4988 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4990 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4991 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4995 assembly->sections [MONO_SECTION_RELOC].size = 12;
4996 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5006 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5010 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5012 ResTreeNode *t1 = (ResTreeNode*)a;
5013 ResTreeNode *t2 = (ResTreeNode*)b;
5015 return t1->id - t2->id;
5019 * resource_tree_create:
5021 * Organize the resources into a resource tree.
5023 static ResTreeNode *
5024 resource_tree_create (MonoArray *win32_resources)
5026 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5030 tree = g_new0 (ResTreeNode, 1);
5032 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5033 MonoReflectionWin32Resource *win32_res =
5034 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5038 /* FIXME: BUG: this stores managed references in unmanaged memory */
5039 lang_node = g_new0 (ResTreeNode, 1);
5040 lang_node->id = win32_res->lang_id;
5041 lang_node->win32_res = win32_res;
5043 /* Create type node if neccesary */
5045 for (l = tree->children; l; l = l->next)
5046 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5047 type_node = (ResTreeNode*)l->data;
5052 type_node = g_new0 (ResTreeNode, 1);
5053 type_node->id = win32_res->res_type;
5056 * The resource types have to be sorted otherwise
5057 * Windows Explorer can't display the version information.
5059 tree->children = g_slist_insert_sorted (tree->children,
5060 type_node, resource_tree_compare_by_id);
5063 /* Create res node if neccesary */
5065 for (l = type_node->children; l; l = l->next)
5066 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5067 res_node = (ResTreeNode*)l->data;
5072 res_node = g_new0 (ResTreeNode, 1);
5073 res_node->id = win32_res->res_id;
5074 type_node->children = g_slist_append (type_node->children, res_node);
5077 res_node->children = g_slist_append (res_node->children, lang_node);
5084 * resource_tree_encode:
5086 * Encode the resource tree into the format used in the PE file.
5089 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5092 MonoPEResourceDir dir;
5093 MonoPEResourceDirEntry dir_entry;
5094 MonoPEResourceDataEntry data_entry;
5096 guint32 res_id_entries;
5099 * For the format of the resource directory, see the article
5100 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5104 memset (&dir, 0, sizeof (dir));
5105 memset (&dir_entry, 0, sizeof (dir_entry));
5106 memset (&data_entry, 0, sizeof (data_entry));
5108 g_assert (sizeof (dir) == 16);
5109 g_assert (sizeof (dir_entry) == 8);
5110 g_assert (sizeof (data_entry) == 16);
5112 node->offset = p - begin;
5114 /* IMAGE_RESOURCE_DIRECTORY */
5115 res_id_entries = g_slist_length (node->children);
5116 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5118 memcpy (p, &dir, sizeof (dir));
5121 /* Reserve space for entries */
5123 p += sizeof (dir_entry) * res_id_entries;
5125 /* Write children */
5126 for (l = node->children; l; l = l->next) {
5127 ResTreeNode *child = (ResTreeNode*)l->data;
5129 if (child->win32_res) {
5132 child->offset = p - begin;
5134 /* IMAGE_RESOURCE_DATA_ENTRY */
5135 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5136 size = mono_array_length (child->win32_res->res_data);
5137 data_entry.rde_size = GUINT32_TO_LE (size);
5139 memcpy (p, &data_entry, sizeof (data_entry));
5140 p += sizeof (data_entry);
5142 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5145 resource_tree_encode (child, begin, p, &p);
5149 /* IMAGE_RESOURCE_ENTRY */
5150 for (l = node->children; l; l = l->next) {
5151 ResTreeNode *child = (ResTreeNode*)l->data;
5153 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5154 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5156 memcpy (entries, &dir_entry, sizeof (dir_entry));
5157 entries += sizeof (dir_entry);
5164 resource_tree_free (ResTreeNode * node)
5167 for (list = node->children; list; list = list->next)
5168 resource_tree_free ((ResTreeNode*)list->data);
5169 g_slist_free(node->children);
5174 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5179 MonoReflectionWin32Resource *win32_res;
5182 if (!assemblyb->win32_resources)
5186 * Resources are stored in a three level tree inside the PE file.
5187 * - level one contains a node for each type of resource
5188 * - level two contains a node for each resource
5189 * - level three contains a node for each instance of a resource for a
5190 * specific language.
5193 tree = resource_tree_create (assemblyb->win32_resources);
5195 /* Estimate the size of the encoded tree */
5197 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5198 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5199 size += mono_array_length (win32_res->res_data);
5201 /* Directory structure */
5202 size += mono_array_length (assemblyb->win32_resources) * 256;
5203 p = buf = g_malloc (size);
5205 resource_tree_encode (tree, p, p, &p);
5207 g_assert (p - buf <= size);
5209 assembly->win32_res = g_malloc (p - buf);
5210 assembly->win32_res_size = p - buf;
5211 memcpy (assembly->win32_res, buf, p - buf);
5214 resource_tree_free (tree);
5218 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5220 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5223 p += sizeof (MonoPEResourceDir);
5224 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5225 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5226 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5227 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5228 fixup_resource_directory (res_section, child, rva);
5230 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5231 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5234 p += sizeof (MonoPEResourceDirEntry);
5239 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5242 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5243 g_error ("WriteFile returned %d\n", GetLastError ());
5246 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5249 * mono_image_create_pefile:
5250 * @mb: a module builder object
5252 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5253 * assembly->pefile where it can be easily retrieved later in chunks.
5256 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5258 MonoMSDOSHeader *msdos;
5259 MonoDotNetHeader *header;
5260 MonoSectionTable *section;
5261 MonoCLIHeader *cli_header;
5262 guint32 size, image_size, virtual_base, text_offset;
5263 guint32 header_start, section_start, file_offset, virtual_offset;
5264 MonoDynamicImage *assembly;
5265 MonoReflectionAssemblyBuilder *assemblyb;
5266 MonoDynamicStream pefile_stream = {0};
5267 MonoDynamicStream *pefile = &pefile_stream;
5269 guint32 *rva, value;
5271 static const unsigned char msheader[] = {
5272 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5273 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5276 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5277 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5278 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5279 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5282 assemblyb = mb->assemblyb;
5284 mono_image_basic_init (assemblyb);
5285 assembly = mb->dynamic_image;
5287 assembly->pe_kind = assemblyb->pe_kind;
5288 assembly->machine = assemblyb->machine;
5289 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5290 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5292 mono_image_build_metadata (mb);
5294 if (mb->is_main && assemblyb->resources) {
5295 int len = mono_array_length (assemblyb->resources);
5296 for (i = 0; i < len; ++i)
5297 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5300 if (mb->resources) {
5301 int len = mono_array_length (mb->resources);
5302 for (i = 0; i < len; ++i)
5303 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5306 build_compressed_metadata (assembly);
5309 assembly_add_win32_resources (assembly, assemblyb);
5311 nsections = calc_section_size (assembly);
5313 /* The DOS header and stub */
5314 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5315 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5317 /* the dotnet header */
5318 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5320 /* the section tables */
5321 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5323 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5324 virtual_offset = VIRT_ALIGN;
5327 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5328 if (!assembly->sections [i].size)
5331 file_offset += FILE_ALIGN - 1;
5332 file_offset &= ~(FILE_ALIGN - 1);
5333 virtual_offset += VIRT_ALIGN - 1;
5334 virtual_offset &= ~(VIRT_ALIGN - 1);
5336 assembly->sections [i].offset = file_offset;
5337 assembly->sections [i].rva = virtual_offset;
5339 file_offset += assembly->sections [i].size;
5340 virtual_offset += assembly->sections [i].size;
5341 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5344 file_offset += FILE_ALIGN - 1;
5345 file_offset &= ~(FILE_ALIGN - 1);
5347 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5349 /* back-patch info */
5350 msdos = (MonoMSDOSHeader*)pefile->data;
5351 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5353 header = (MonoDotNetHeader*)(pefile->data + header_start);
5354 header->pesig [0] = 'P';
5355 header->pesig [1] = 'E';
5357 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5358 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5359 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5360 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5361 if (assemblyb->pekind == 1) {
5363 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5366 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5369 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5371 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5372 header->pe.pe_major = 6;
5373 header->pe.pe_minor = 0;
5374 size = assembly->sections [MONO_SECTION_TEXT].size;
5375 size += FILE_ALIGN - 1;
5376 size &= ~(FILE_ALIGN - 1);
5377 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5378 size = assembly->sections [MONO_SECTION_RSRC].size;
5379 size += FILE_ALIGN - 1;
5380 size &= ~(FILE_ALIGN - 1);
5381 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5382 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5383 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5384 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5385 /* pe_rva_entry_point always at the beginning of the text section */
5386 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5388 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5389 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5390 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5391 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5392 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5393 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5394 size = section_start;
5395 size += FILE_ALIGN - 1;
5396 size &= ~(FILE_ALIGN - 1);
5397 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5399 size += VIRT_ALIGN - 1;
5400 size &= ~(VIRT_ALIGN - 1);
5401 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5404 // Translate the PEFileKind value to the value expected by the Windows loader
5410 // PEFileKinds.Dll == 1
5411 // PEFileKinds.ConsoleApplication == 2
5412 // PEFileKinds.WindowApplication == 3
5415 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5416 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5418 if (assemblyb->pekind == 3)
5423 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5425 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5426 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5427 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5428 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5429 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5430 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5432 /* fill data directory entries */
5434 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5435 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5437 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5438 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5440 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5441 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5442 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5443 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5444 /* patch entrypoint name */
5445 if (assemblyb->pekind == 1)
5446 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5448 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5449 /* patch imported function RVA name */
5450 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5451 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5453 /* the import table */
5454 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5455 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5456 /* patch imported dll RVA name and other entries in the dir */
5457 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5458 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5459 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5460 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5461 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5462 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5464 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5465 value = (assembly->text_rva + assembly->imp_names_offset);
5466 *p++ = (value) & 0xff;
5467 *p++ = (value >> 8) & (0xff);
5468 *p++ = (value >> 16) & (0xff);
5469 *p++ = (value >> 24) & (0xff);
5471 /* the CLI header info */
5472 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5473 cli_header->ch_size = GUINT32_FROM_LE (72);
5474 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5475 if (mono_framework_version () > 1)
5476 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5478 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5479 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5480 if (assemblyb->entry_point) {
5481 guint32 table_idx = 0;
5482 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5483 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5484 table_idx = methodb->table_idx;
5486 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5488 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5490 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5492 /* The embedded managed resources */
5493 text_offset = assembly->text_rva + assembly->code.index;
5494 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5495 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5496 text_offset += assembly->resources.index;
5497 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5498 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5499 text_offset += assembly->meta_size;
5500 if (assembly->strong_name_size) {
5501 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5502 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5503 text_offset += assembly->strong_name_size;
5506 /* write the section tables and section content */
5507 section = (MonoSectionTable*)(pefile->data + section_start);
5508 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5509 static const char section_names [][7] = {
5510 ".text", ".rsrc", ".reloc"
5512 if (!assembly->sections [i].size)
5514 strcpy (section->st_name, section_names [i]);
5515 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5516 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5517 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5518 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5519 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5520 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5521 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5525 checked_write_file (file, pefile->data, pefile->index);
5527 mono_dynamic_stream_reset (pefile);
5529 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5530 if (!assembly->sections [i].size)
5533 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5534 g_error ("SetFilePointer returned %d\n", GetLastError ());
5537 case MONO_SECTION_TEXT:
5538 /* patch entry point */
5539 p = (guchar*)(assembly->code.data + 2);
5540 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5541 *p++ = (value) & 0xff;
5542 *p++ = (value >> 8) & 0xff;
5543 *p++ = (value >> 16) & 0xff;
5544 *p++ = (value >> 24) & 0xff;
5546 checked_write_file (file, assembly->code.data, assembly->code.index);
5547 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5548 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5549 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5552 g_free (assembly->image.raw_metadata);
5554 case MONO_SECTION_RELOC: {
5558 guint16 type_and_offset;
5562 g_assert (sizeof (reloc) == 12);
5564 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5565 reloc.block_size = GUINT32_FROM_LE (12);
5568 * the entrypoint is always at the start of the text section
5569 * 3 is IMAGE_REL_BASED_HIGHLOW
5570 * 2 is patch_size_rva - text_rva
5572 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5575 checked_write_file (file, &reloc, sizeof (reloc));
5579 case MONO_SECTION_RSRC:
5580 if (assembly->win32_res) {
5582 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5583 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5584 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5588 g_assert_not_reached ();
5592 /* check that the file is properly padded */
5593 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5594 g_error ("SetFilePointer returned %d\n", GetLastError ());
5595 if (! SetEndOfFile (file))
5596 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5598 mono_dynamic_stream_reset (&assembly->code);
5599 mono_dynamic_stream_reset (&assembly->us);
5600 mono_dynamic_stream_reset (&assembly->blob);
5601 mono_dynamic_stream_reset (&assembly->guid);
5602 mono_dynamic_stream_reset (&assembly->sheap);
5604 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5605 g_hash_table_destroy (assembly->blob_cache);
5606 assembly->blob_cache = NULL;
5609 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5612 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5614 g_assert_not_reached ();
5617 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5619 #ifndef DISABLE_REFLECTION_EMIT
5621 MonoReflectionModule *
5622 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5626 MonoImageOpenStatus status;
5627 MonoDynamicAssembly *assembly;
5628 guint32 module_count;
5629 MonoImage **new_modules;
5630 gboolean *new_modules_loaded;
5632 name = mono_string_to_utf8 (fileName);
5634 image = mono_image_open (name, &status);
5637 if (status == MONO_IMAGE_ERROR_ERRNO)
5638 exc = mono_get_exception_file_not_found (fileName);
5640 exc = mono_get_exception_bad_image_format (name);
5642 mono_raise_exception (exc);
5647 assembly = ab->dynamic_assembly;
5648 image->assembly = (MonoAssembly*)assembly;
5650 module_count = image->assembly->image->module_count;
5651 new_modules = g_new0 (MonoImage *, module_count + 1);
5652 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5654 if (image->assembly->image->modules)
5655 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5656 if (image->assembly->image->modules_loaded)
5657 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5658 new_modules [module_count] = image;
5659 new_modules_loaded [module_count] = TRUE;
5660 mono_image_addref (image);
5662 g_free (image->assembly->image->modules);
5663 image->assembly->image->modules = new_modules;
5664 image->assembly->image->modules_loaded = new_modules_loaded;
5665 image->assembly->image->module_count ++;
5667 mono_assembly_load_references (image, &status);
5669 mono_image_close (image);
5670 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5673 return mono_module_get_object (mono_domain_get (), image);
5676 #endif /* DISABLE_REFLECTION_EMIT */
5679 * We need to return always the same object for MethodInfo, FieldInfo etc..
5680 * but we need to consider the reflected type.
5681 * type uses a different hash, since it uses custom hash/equal functions.
5686 MonoClass *refclass;
5690 reflected_equal (gconstpointer a, gconstpointer b) {
5691 const ReflectedEntry *ea = a;
5692 const ReflectedEntry *eb = b;
5694 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5698 reflected_hash (gconstpointer a) {
5699 const ReflectedEntry *ea = a;
5700 return mono_aligned_addr_hash (ea->item);
5703 #define CHECK_OBJECT(t,p,k) \
5709 mono_domain_lock (domain); \
5710 if (!domain->refobject_hash) \
5711 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5712 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5713 mono_domain_unlock (domain); \
5716 mono_domain_unlock (domain); \
5719 #ifdef HAVE_BOEHM_GC
5720 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5722 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5725 #define CACHE_OBJECT(t,p,o,k) \
5728 ReflectedEntry pe; \
5730 pe.refclass = (k); \
5731 mono_domain_lock (domain); \
5732 if (!domain->refobject_hash) \
5733 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5734 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5736 ReflectedEntry *e = ALLOC_REFENTRY; \
5738 e->refclass = (k); \
5739 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5742 mono_domain_unlock (domain); \
5747 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5749 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5753 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5755 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5758 #ifndef DISABLE_REFLECTION_EMIT
5761 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5763 MonoDynamicImage *image = moduleb->dynamic_image;
5764 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5767 MonoImage **new_modules;
5770 * FIXME: we already created an image in mono_image_basic_init (), but
5771 * we don't know which module it belongs to, since that is only
5772 * determined at assembly save time.
5774 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5775 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5777 moduleb->module.image = &image->image;
5778 moduleb->dynamic_image = image;
5779 register_module (mono_object_domain (moduleb), moduleb, image);
5781 /* register the module with the assembly */
5782 ass = ab->dynamic_assembly->assembly.image;
5783 module_count = ass->module_count;
5784 new_modules = g_new0 (MonoImage *, module_count + 1);
5787 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5788 new_modules [module_count] = &image->image;
5789 mono_image_addref (&image->image);
5791 g_free (ass->modules);
5792 ass->modules = new_modules;
5793 ass->module_count ++;
5800 * mono_assembly_get_object:
5801 * @domain: an app domain
5802 * @assembly: an assembly
5804 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5806 MonoReflectionAssembly*
5807 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5809 static MonoClass *System_Reflection_Assembly;
5810 MonoReflectionAssembly *res;
5812 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5813 if (!System_Reflection_Assembly)
5814 System_Reflection_Assembly = mono_class_from_name (
5815 mono_defaults.corlib, "System.Reflection", "Assembly");
5816 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5817 res->assembly = assembly;
5819 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5824 MonoReflectionModule*
5825 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5827 static MonoClass *System_Reflection_Module;
5828 MonoReflectionModule *res;
5831 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5832 if (!System_Reflection_Module)
5833 System_Reflection_Module = mono_class_from_name (
5834 mono_defaults.corlib, "System.Reflection", "Module");
5835 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5838 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5840 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5841 basename = g_path_get_basename (image->name);
5842 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5843 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5847 if (image->assembly->image == image) {
5848 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5852 if (image->assembly->image->modules) {
5853 for (i = 0; i < image->assembly->image->module_count; i++) {
5854 if (image->assembly->image->modules [i] == image)
5855 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5857 g_assert (res->token);
5861 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5864 MonoReflectionModule*
5865 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5867 static MonoClass *System_Reflection_Module;
5868 MonoReflectionModule *res;
5869 MonoTableInfo *table;
5870 guint32 cols [MONO_FILE_SIZE];
5872 guint32 i, name_idx;
5875 if (!System_Reflection_Module)
5876 System_Reflection_Module = mono_class_from_name (
5877 mono_defaults.corlib, "System.Reflection", "Module");
5878 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5880 table = &image->tables [MONO_TABLE_FILE];
5881 g_assert (table_index < table->rows);
5882 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5885 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5886 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5888 /* Check whenever the row has a corresponding row in the moduleref table */
5889 table = &image->tables [MONO_TABLE_MODULEREF];
5890 for (i = 0; i < table->rows; ++i) {
5891 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5892 val = mono_metadata_string_heap (image, name_idx);
5893 if (strcmp (val, name) == 0)
5894 res->image = image->modules [i];
5897 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5898 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5899 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5900 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5901 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5907 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5909 if ((t1->type != t2->type) ||
5910 (t1->byref != t2->byref))
5914 case MONO_TYPE_VOID:
5915 case MONO_TYPE_BOOLEAN:
5916 case MONO_TYPE_CHAR:
5927 case MONO_TYPE_STRING:
5930 case MONO_TYPE_OBJECT:
5931 case MONO_TYPE_TYPEDBYREF:
5933 case MONO_TYPE_VALUETYPE:
5934 case MONO_TYPE_CLASS:
5935 case MONO_TYPE_SZARRAY:
5936 return t1->data.klass == t2->data.klass;
5938 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5939 case MONO_TYPE_ARRAY:
5940 if (t1->data.array->rank != t2->data.array->rank)
5942 return t1->data.array->eklass == t2->data.array->eklass;
5943 case MONO_TYPE_GENERICINST: {
5945 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5946 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5947 if (i1->type_argc != i2->type_argc)
5949 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5950 &t2->data.generic_class->container_class->byval_arg))
5952 /* FIXME: we should probably just compare the instance pointers directly. */
5953 for (i = 0; i < i1->type_argc; ++i) {
5954 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5960 case MONO_TYPE_MVAR:
5961 return t1->data.generic_param == t2->data.generic_param;
5963 g_error ("implement type compare for %0x!", t1->type);
5971 mymono_metadata_type_hash (MonoType *t1)
5977 hash |= t1->byref << 6; /* do not collide with t1->type values */
5979 case MONO_TYPE_VALUETYPE:
5980 case MONO_TYPE_CLASS:
5981 case MONO_TYPE_SZARRAY:
5982 /* check if the distribution is good enough */
5983 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5985 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5986 case MONO_TYPE_GENERICINST: {
5988 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5989 hash += g_str_hash (t1->data.generic_class->container_class->name);
5991 for (i = 0; i < inst->type_argc; ++i) {
5992 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6001 static MonoReflectionGenericClass*
6002 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6004 static MonoClass *System_Reflection_MonoGenericClass;
6005 MonoReflectionGenericClass *res;
6006 MonoClass *klass, *gklass;
6008 if (!System_Reflection_MonoGenericClass) {
6009 System_Reflection_MonoGenericClass = mono_class_from_name (
6010 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6011 g_assert (System_Reflection_MonoGenericClass);
6014 klass = mono_class_from_mono_type (geninst);
6015 gklass = klass->generic_class->container_class;
6017 mono_class_init (klass);
6020 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6022 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6025 res->type.type = geninst;
6026 g_assert (gklass->reflection_info);
6027 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6028 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6034 verify_safe_for_managed_space (MonoType *type)
6036 switch (type->type) {
6038 case MONO_TYPE_ARRAY:
6039 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6041 return verify_safe_for_managed_space (type->data.type);
6042 case MONO_TYPE_SZARRAY:
6043 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6044 case MONO_TYPE_GENERICINST: {
6045 MonoGenericInst *inst = type->data.generic_class->inst;
6049 for (i = 0; i < inst->type_argc; ++i)
6050 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6056 case MONO_TYPE_MVAR:
6063 * mono_type_get_object:
6064 * @domain: an app domain
6067 * Return an System.MonoType object representing the type @type.
6070 mono_type_get_object (MonoDomain *domain, MonoType *type)
6072 MonoReflectionType *res;
6073 MonoClass *klass = mono_class_from_mono_type (type);
6075 /*we must avoid using @type as it might have come
6076 * from a mono_metadata_type_dup and the caller
6077 * expects that is can be freed.
6078 * Using the right type from
6080 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6082 /* void is very common */
6083 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6084 return (MonoReflectionType*)domain->typeof_void;
6087 * If the vtable of the given class was already created, we can use
6088 * the MonoType from there and avoid all locking and hash table lookups.
6090 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6091 * that the resulting object is diferent.
6093 if (type == &klass->byval_arg && !klass->image->dynamic) {
6094 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6095 if (vtable && vtable->type)
6096 return vtable->type;
6099 mono_domain_lock (domain);
6100 if (!domain->type_hash)
6101 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6102 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6103 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6104 mono_domain_unlock (domain);
6107 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6108 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6109 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6110 mono_g_hash_table_insert (domain->type_hash, type, res);
6111 mono_domain_unlock (domain);
6115 if (!verify_safe_for_managed_space (type)) {
6116 mono_domain_unlock (domain);
6117 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6120 if (klass->reflection_info && !klass->wastypebuilder) {
6121 /* g_assert_not_reached (); */
6122 /* should this be considered an error condition? */
6124 mono_domain_unlock (domain);
6125 return klass->reflection_info;
6128 // FIXME: Get rid of this, do it in the icalls for Type
6129 mono_class_init (klass);
6131 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6133 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6136 mono_g_hash_table_insert (domain->type_hash, type, res);
6138 if (type->type == MONO_TYPE_VOID)
6139 MONO_OBJECT_SETREF (domain, typeof_void, res);
6141 mono_domain_unlock (domain);
6146 * mono_method_get_object:
6147 * @domain: an app domain
6149 * @refclass: the reflected type (can be NULL)
6151 * Return an System.Reflection.MonoMethod object representing the method @method.
6153 MonoReflectionMethod*
6154 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6157 * We use the same C representation for methods and constructors, but the type
6158 * name in C# is different.
6160 static MonoClass *System_Reflection_MonoMethod = NULL;
6161 static MonoClass *System_Reflection_MonoCMethod = NULL;
6162 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6163 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6165 MonoReflectionMethod *ret;
6168 * Don't let static RGCTX invoke wrappers get into
6169 * MonoReflectionMethods.
6171 if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
6172 method = mono_marshal_method_from_wrapper (method);
6174 if (method->is_inflated) {
6175 MonoReflectionGenericMethod *gret;
6177 refclass = method->klass;
6178 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6179 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6180 if (!System_Reflection_MonoGenericCMethod)
6181 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6182 klass = System_Reflection_MonoGenericCMethod;
6184 if (!System_Reflection_MonoGenericMethod)
6185 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6186 klass = System_Reflection_MonoGenericMethod;
6188 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6189 gret->method.method = method;
6190 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6191 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6192 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6196 refclass = method->klass;
6198 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6199 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6200 if (!System_Reflection_MonoCMethod)
6201 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6202 klass = System_Reflection_MonoCMethod;
6205 if (!System_Reflection_MonoMethod)
6206 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6207 klass = System_Reflection_MonoMethod;
6209 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6210 ret->method = method;
6211 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6212 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6216 * mono_field_get_object:
6217 * @domain: an app domain
6221 * Return an System.Reflection.MonoField object representing the field @field
6224 MonoReflectionField*
6225 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6227 MonoReflectionField *res;
6228 static MonoClass *monofield_klass;
6230 CHECK_OBJECT (MonoReflectionField *, field, klass);
6231 if (!monofield_klass)
6232 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6233 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6236 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6237 if (is_field_on_inst (field))
6238 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6240 res->attrs = field->type->attrs;
6241 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6242 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6246 * mono_property_get_object:
6247 * @domain: an app domain
6249 * @property: a property
6251 * Return an System.Reflection.MonoProperty object representing the property @property
6254 MonoReflectionProperty*
6255 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6257 MonoReflectionProperty *res;
6258 static MonoClass *monoproperty_klass;
6260 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6261 if (!monoproperty_klass)
6262 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6263 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6265 res->property = property;
6266 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6270 * mono_event_get_object:
6271 * @domain: an app domain
6275 * Return an System.Reflection.MonoEvent object representing the event @event
6278 MonoReflectionEvent*
6279 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6281 MonoReflectionEvent *res;
6282 static MonoClass *monoevent_klass;
6284 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6285 if (!monoevent_klass)
6286 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6287 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6290 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6294 * mono_get_reflection_missing_object:
6295 * @domain: Domain where the object lives
6297 * Returns the System.Reflection.Missing.Value singleton object
6298 * (of type System.Reflection.Missing).
6300 * Used as the value for ParameterInfo.DefaultValue when Optional
6304 mono_get_reflection_missing_object (MonoDomain *domain)
6307 static MonoClassField *missing_value_field = NULL;
6309 if (!missing_value_field) {
6310 MonoClass *missing_klass;
6311 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6312 mono_class_init (missing_klass);
6313 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6314 g_assert (missing_value_field);
6316 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6322 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6325 *dbnull = mono_get_dbnull_object (domain);
6330 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6332 if (!*reflection_missing)
6333 *reflection_missing = mono_get_reflection_missing_object (domain);
6334 return *reflection_missing;
6338 * mono_param_get_objects:
6339 * @domain: an app domain
6342 * Return an System.Reflection.ParameterInfo array object representing the parameters
6343 * in the method @method.
6346 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6348 static MonoClass *System_Reflection_ParameterInfo;
6349 static MonoClass *System_Reflection_ParameterInfo_array;
6350 MonoArray *res = NULL;
6351 MonoReflectionMethod *member = NULL;
6352 MonoReflectionParameter *param = NULL;
6353 char **names, **blobs = NULL;
6354 guint32 *types = NULL;
6355 MonoType *type = NULL;
6356 MonoObject *dbnull = NULL;
6357 MonoObject *missing = NULL;
6358 MonoMarshalSpec **mspecs;
6359 MonoMethodSignature *sig;
6360 MonoVTable *pinfo_vtable;
6363 if (!System_Reflection_ParameterInfo_array) {
6366 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6367 mono_memory_barrier ();
6368 System_Reflection_ParameterInfo = klass;
6370 klass = mono_array_class_get (klass, 1);
6371 mono_memory_barrier ();
6372 System_Reflection_ParameterInfo_array = klass;
6375 if (!mono_method_signature (method)->param_count)
6376 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6378 /* Note: the cache is based on the address of the signature into the method
6379 * since we already cache MethodInfos with the method as keys.
6381 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6383 sig = mono_method_signature (method);
6384 member = mono_method_get_object (domain, method, NULL);
6385 names = g_new (char *, sig->param_count);
6386 mono_method_get_param_names (method, (const char **) names);
6388 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6389 mono_method_get_marshal_info (method, mspecs);
6391 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6392 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6393 for (i = 0; i < sig->param_count; ++i) {
6394 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6395 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6396 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6397 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6398 param->PositionImpl = i;
6399 param->AttrsImpl = sig->params [i]->attrs;
6401 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6402 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6403 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6405 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6409 blobs = g_new0 (char *, sig->param_count);
6410 types = g_new0 (guint32, sig->param_count);
6411 get_default_param_value_blobs (method, blobs, types);
6414 /* Build MonoType for the type from the Constant Table */
6416 type = g_new0 (MonoType, 1);
6417 type->type = types [i];
6418 type->data.klass = NULL;
6419 if (types [i] == MONO_TYPE_CLASS)
6420 type->data.klass = mono_defaults.object_class;
6421 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6422 /* For enums, types [i] contains the base type */
6424 type->type = MONO_TYPE_VALUETYPE;
6425 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6427 type->data.klass = mono_class_from_mono_type (type);
6429 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6431 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6432 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6433 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6434 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6436 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6442 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6444 mono_array_setref (res, i, param);
6451 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6453 mono_metadata_free_marshal_spec (mspecs [i]);
6456 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6460 * mono_method_body_get_object:
6461 * @domain: an app domain
6464 * Return an System.Reflection.MethodBody object representing the method @method.
6466 MonoReflectionMethodBody*
6467 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6469 static MonoClass *System_Reflection_MethodBody = NULL;
6470 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6471 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6472 MonoReflectionMethodBody *ret;
6473 MonoMethodNormal *mn;
6474 MonoMethodHeader *header;
6475 guint32 method_rva, local_var_sig_token;
6477 unsigned char format, flags;
6480 if (!System_Reflection_MethodBody)
6481 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6482 if (!System_Reflection_LocalVariableInfo)
6483 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6484 if (!System_Reflection_ExceptionHandlingClause)
6485 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6487 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6489 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6490 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6491 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6492 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6494 mn = (MonoMethodNormal *)method;
6495 header = mono_method_get_header (method);
6497 /* Obtain local vars signature token */
6498 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6499 ptr = mono_image_rva_map (method->klass->image, method_rva);
6500 flags = *(const unsigned char *) ptr;
6501 format = flags & METHOD_HEADER_FORMAT_MASK;
6503 case METHOD_HEADER_TINY_FORMAT:
6504 case METHOD_HEADER_TINY_FORMAT1:
6505 local_var_sig_token = 0;
6507 case METHOD_HEADER_FAT_FORMAT:
6511 local_var_sig_token = read32 (ptr);
6514 g_assert_not_reached ();
6517 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6519 ret->init_locals = header->init_locals;
6520 ret->max_stack = header->max_stack;
6521 ret->local_var_sig_token = local_var_sig_token;
6522 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6523 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6526 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6527 for (i = 0; i < header->num_locals; ++i) {
6528 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6529 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6530 info->is_pinned = header->locals [i]->pinned;
6531 info->local_index = i;
6532 mono_array_setref (ret->locals, i, info);
6536 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6537 for (i = 0; i < header->num_clauses; ++i) {
6538 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6539 MonoExceptionClause *clause = &header->clauses [i];
6541 info->flags = clause->flags;
6542 info->try_offset = clause->try_offset;
6543 info->try_length = clause->try_len;
6544 info->handler_offset = clause->handler_offset;
6545 info->handler_length = clause->handler_len;
6546 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6547 info->filter_offset = clause->data.filter_offset;
6548 else if (clause->data.catch_class)
6549 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6551 mono_array_setref (ret->clauses, i, info);
6554 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6559 * mono_get_dbnull_object:
6560 * @domain: Domain where the object lives
6562 * Returns the System.DBNull.Value singleton object
6564 * Used as the value for ParameterInfo.DefaultValue
6567 mono_get_dbnull_object (MonoDomain *domain)
6570 static MonoClassField *dbnull_value_field = NULL;
6572 if (!dbnull_value_field) {
6573 MonoClass *dbnull_klass;
6574 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6575 mono_class_init (dbnull_klass);
6576 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6577 g_assert (dbnull_value_field);
6579 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6585 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6587 guint32 param_index, i, lastp, crow = 0;
6588 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6591 MonoClass *klass = method->klass;
6592 MonoImage *image = klass->image;
6593 MonoMethodSignature *methodsig = mono_method_signature (method);
6595 MonoTableInfo *constt;
6596 MonoTableInfo *methodt;
6597 MonoTableInfo *paramt;
6599 if (!methodsig->param_count)
6602 mono_class_init (klass);
6604 if (klass->image->dynamic) {
6605 MonoReflectionMethodAux *aux;
6606 if (method->is_inflated)
6607 method = ((MonoMethodInflated*)method)->declaring;
6608 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6609 if (aux && aux->param_defaults) {
6610 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6611 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6616 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6617 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6618 constt = &image->tables [MONO_TABLE_CONSTANT];
6620 idx = mono_method_get_index (method) - 1;
6621 g_assert (idx != -1);
6623 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6624 if (idx + 1 < methodt->rows)
6625 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6627 lastp = paramt->rows + 1;
6629 for (i = param_index; i < lastp; ++i) {
6632 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6633 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6635 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6638 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6643 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6644 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6645 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6652 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6657 MonoType *basetype = type;
6662 klass = mono_class_from_mono_type (type);
6663 if (klass->valuetype) {
6664 object = mono_object_new (domain, klass);
6665 retval = ((gchar *) object + sizeof (MonoObject));
6666 if (klass->enumtype)
6667 basetype = klass->enum_basetype;
6672 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6679 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6683 memset (assembly, 0, sizeof (MonoAssemblyName));
6685 assembly->culture = "";
6686 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6688 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6691 while (g_ascii_isspace (*p) || *p == ',') {
6700 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6702 assembly->major = strtoul (p, &s, 10);
6703 if (s == p || *s != '.')
6706 assembly->minor = strtoul (p, &s, 10);
6707 if (s == p || *s != '.')
6710 assembly->build = strtoul (p, &s, 10);
6711 if (s == p || *s != '.')
6714 assembly->revision = strtoul (p, &s, 10);
6718 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6720 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6721 assembly->culture = "";
6724 assembly->culture = p;
6725 while (*p && *p != ',') {
6729 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6731 if (strncmp (p, "null", 4) == 0) {
6736 while (*p && *p != ',') {
6739 len = (p - start + 1);
6740 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6741 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6742 g_strlcpy ((char*)assembly->public_key_token, start, len);
6745 while (*p && *p != ',')
6749 while (g_ascii_isspace (*p) || *p == ',') {
6763 * mono_reflection_parse_type:
6766 * Parse a type name as accepted by the GetType () method and output the info
6767 * extracted in the info structure.
6768 * the name param will be mangled, so, make a copy before passing it to this function.
6769 * The fields in info will be valid until the memory pointed to by name is valid.
6771 * See also mono_type_get_name () below.
6773 * Returns: 0 on parse error.
6776 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6777 MonoTypeNameParse *info)
6779 char *start, *p, *w, *temp, *last_point, *startn;
6780 int in_modifiers = 0;
6781 int isbyref = 0, rank, arity = 0, i;
6783 start = p = w = name;
6785 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6786 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6787 info->name = info->name_space = NULL;
6788 info->nested = NULL;
6789 info->modifiers = NULL;
6790 info->type_arguments = NULL;
6792 /* last_point separates the namespace from the name */
6795 while (*p == ' ') p++, start++, w++, name++;
6800 *p = 0; /* NULL terminate the name */
6802 info->nested = g_list_append (info->nested, startn);
6803 /* we have parsed the nesting namespace + name */
6807 info->name_space = start;
6809 info->name = last_point + 1;
6811 info->name_space = (char *)"";
6830 i = strtol (p, &temp, 10);
6847 info->name_space = start;
6849 info->name = last_point + 1;
6851 info->name_space = (char *)"";
6858 if (isbyref) /* only one level allowed by the spec */
6861 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6865 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6871 info->type_arguments = g_ptr_array_new ();
6872 for (i = 0; i < arity; i++) {
6873 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6874 gboolean fqname = FALSE;
6876 g_ptr_array_add (info->type_arguments, subinfo);
6883 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6894 while (*p && (*p != ']'))
6902 if (g_ascii_isspace (*aname)) {
6909 !assembly_name_to_aname (&subinfo->assembly, aname))
6913 if (i + 1 < arity) {
6933 else if (*p == '*') /* '*' means unknown lower bound */
6934 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6941 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6952 if (g_ascii_isspace (*p)) {
6959 return 0; /* missing assembly name */
6960 if (!assembly_name_to_aname (&info->assembly, p))
6966 if (info->assembly.name)
6969 // *w = 0; /* terminate class name */
6971 if (!info->name || !*info->name)
6975 /* add other consistency checks */
6980 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6982 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6986 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6988 gboolean type_resolve = FALSE;
6990 MonoImage *rootimage = image;
6992 if (info->assembly.name) {
6993 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6994 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
6996 * This could happen in the AOT compiler case when the search hook is not
6999 assembly = image->assembly;
7001 /* then we must load the assembly ourselve - see #60439 */
7002 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7006 image = assembly->image;
7007 } else if (!image) {
7008 image = mono_defaults.corlib;
7011 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7012 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7013 image = mono_defaults.corlib;
7014 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7021 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7026 gboolean bounded = FALSE;
7029 image = mono_defaults.corlib;
7032 klass = mono_class_from_name_case (image, info->name_space, info->name);
7034 klass = mono_class_from_name (image, info->name_space, info->name);
7037 for (mod = info->nested; mod; mod = mod->next) {
7038 gpointer iter = NULL;
7042 mono_class_init (parent);
7044 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7046 if (g_strcasecmp (klass->name, mod->data) == 0)
7049 if (strcmp (klass->name, mod->data) == 0)
7058 mono_class_init (klass);
7060 if (info->type_arguments) {
7061 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7062 MonoReflectionType *the_type;
7066 for (i = 0; i < info->type_arguments->len; i++) {
7067 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7069 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7070 if (!type_args [i]) {
7076 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7078 instance = mono_reflection_bind_generic_parameters (
7079 the_type, info->type_arguments->len, type_args);
7085 klass = mono_class_from_mono_type (instance);
7088 for (mod = info->modifiers; mod; mod = mod->next) {
7089 modval = GPOINTER_TO_UINT (mod->data);
7090 if (!modval) { /* byref: must be last modifier */
7091 return &klass->this_arg;
7092 } else if (modval == -1) {
7093 klass = mono_ptr_class_get (&klass->byval_arg);
7094 } else if (modval == -2) {
7096 } else { /* array rank */
7097 klass = mono_bounded_array_class_get (klass, modval, bounded);
7099 mono_class_init (klass);
7102 return &klass->byval_arg;
7106 * mono_reflection_get_type:
7107 * @image: a metadata context
7108 * @info: type description structure
7109 * @ignorecase: flag for case-insensitive string compares
7110 * @type_resolve: whenever type resolve was already tried
7112 * Build a MonoType from the type description in @info.
7117 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7118 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7122 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7124 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7128 g_assert (assembly->dynamic);
7130 /* Enumerate all modules */
7133 if (abuilder->modules) {
7134 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7135 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7136 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7142 if (!type && abuilder->loaded_modules) {
7143 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7144 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7145 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7155 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7158 MonoReflectionAssembly *assembly;
7162 if (image && image->dynamic)
7163 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7165 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7168 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7175 *type_resolve = TRUE;
7178 /* Reconstruct the type name */
7179 fullName = g_string_new ("");
7180 if (info->name_space && (info->name_space [0] != '\0'))
7181 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7183 g_string_printf (fullName, info->name);
7184 for (mod = info->nested; mod; mod = mod->next)
7185 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7187 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7189 if (assembly->assembly->dynamic)
7190 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7192 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7195 g_string_free (fullName, TRUE);
7200 mono_reflection_free_type_info (MonoTypeNameParse *info)
7202 g_list_free (info->modifiers);
7203 g_list_free (info->nested);
7205 if (info->type_arguments) {
7208 for (i = 0; i < info->type_arguments->len; i++) {
7209 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7211 mono_reflection_free_type_info (subinfo);
7212 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7216 g_ptr_array_free (info->type_arguments, TRUE);
7221 * mono_reflection_type_from_name:
7223 * @image: a metadata context (can be NULL).
7225 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7226 * it defaults to get the type from @image or, if @image is NULL or loading
7227 * from it fails, uses corlib.
7231 mono_reflection_type_from_name (char *name, MonoImage *image)
7233 MonoType *type = NULL;
7234 MonoTypeNameParse info;
7237 /* Make a copy since parse_type modifies its argument */
7238 tmp = g_strdup (name);
7240 /*g_print ("requested type %s\n", str);*/
7241 if (mono_reflection_parse_type (tmp, &info)) {
7242 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7246 mono_reflection_free_type_info (&info);
7251 * mono_reflection_get_token:
7253 * Return the metadata token of OBJ which should be an object
7254 * representing a metadata element.
7257 mono_reflection_get_token (MonoObject *obj)
7262 klass = obj->vtable->klass;
7264 if (strcmp (klass->name, "MethodBuilder") == 0) {
7265 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7267 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7268 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7269 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7271 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7272 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7273 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7275 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7276 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7277 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7278 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7279 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7280 } else if (strcmp (klass->name, "MonoType") == 0) {
7281 MonoReflectionType *tb = (MonoReflectionType *)obj;
7282 token = mono_class_from_mono_type (tb->type)->type_token;
7283 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7284 strcmp (klass->name, "MonoMethod") == 0 ||
7285 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7286 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7287 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7288 if (m->method->is_inflated) {
7289 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7290 return inflated->declaring->token;
7292 token = m->method->token;
7294 } else if (strcmp (klass->name, "MonoField") == 0) {
7295 MonoReflectionField *f = (MonoReflectionField*)obj;
7297 if (is_field_on_inst (f->field)) {
7298 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7299 int field_index = f->field - dgclass->fields;
7302 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7303 obj = dgclass->field_objects [field_index];
7304 return mono_reflection_get_token (obj);
7306 token = mono_class_get_field_token (f->field);
7307 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7308 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7310 token = mono_class_get_property_token (p->property);
7311 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7312 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7314 token = mono_class_get_event_token (p->event);
7315 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7316 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7318 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7319 } else if (strcmp (klass->name, "Module") == 0) {
7320 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7323 } else if (strcmp (klass->name, "Assembly") == 0) {
7324 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7326 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7327 MonoException *ex = mono_get_exception_not_implemented (msg);
7329 mono_raise_exception (ex);
7336 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7338 int slen, type = t->type;
7339 MonoClass *tklass = t->data.klass;
7345 case MONO_TYPE_BOOLEAN: {
7346 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7351 case MONO_TYPE_CHAR:
7353 case MONO_TYPE_I2: {
7354 guint16 *val = g_malloc (sizeof (guint16));
7359 #if SIZEOF_VOID_P == 4
7365 case MONO_TYPE_I4: {
7366 guint32 *val = g_malloc (sizeof (guint32));
7371 #if SIZEOF_VOID_P == 8
7372 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7376 case MONO_TYPE_I8: {
7377 guint64 *val = g_malloc (sizeof (guint64));
7382 case MONO_TYPE_R8: {
7383 double *val = g_malloc (sizeof (double));
7388 case MONO_TYPE_VALUETYPE:
7389 if (t->data.klass->enumtype) {
7390 type = t->data.klass->enum_basetype->type;
7393 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7396 case MONO_TYPE_STRING:
7397 if (*p == (char)0xFF) {
7401 slen = mono_metadata_decode_value (p, &p);
7403 return mono_string_new_len (mono_domain_get (), p, slen);
7404 case MONO_TYPE_CLASS: {
7407 if (*p == (char)0xFF) {
7412 slen = mono_metadata_decode_value (p, &p);
7413 n = g_memdup (p, slen + 1);
7415 t = mono_reflection_type_from_name (n, image);
7417 g_warning ("Cannot load type '%s'", n);
7421 return mono_type_get_object (mono_domain_get (), t);
7425 case MONO_TYPE_OBJECT: {
7428 MonoClass *subc = NULL;
7433 } else if (subt == 0x0E) {
7434 type = MONO_TYPE_STRING;
7436 } else if (subt == 0x1D) {
7437 MonoType simple_type = {{0}};
7442 /* See Partition II, Appendix B3 */
7443 etype = MONO_TYPE_OBJECT;
7444 type = MONO_TYPE_SZARRAY;
7445 simple_type.type = etype;
7446 tklass = mono_class_from_mono_type (&simple_type);
7448 } else if (subt == 0x55) {
7451 slen = mono_metadata_decode_value (p, &p);
7452 n = g_memdup (p, slen + 1);
7454 t = mono_reflection_type_from_name (n, image);
7456 g_error ("Cannot load type '%s'", n);
7459 subc = mono_class_from_mono_type (t);
7460 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7461 MonoType simple_type = {{0}};
7462 simple_type.type = subt;
7463 subc = mono_class_from_mono_type (&simple_type);
7465 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7467 val = load_cattr_value (image, &subc->byval_arg, p, end);
7468 obj = mono_object_new (mono_domain_get (), subc);
7469 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7473 case MONO_TYPE_SZARRAY: {
7475 guint32 i, alen, basetype;
7478 if (alen == 0xffffffff) {
7482 arr = mono_array_new (mono_domain_get(), tklass, alen);
7483 basetype = tklass->byval_arg.type;
7484 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7485 basetype = tklass->enum_basetype->type;
7490 case MONO_TYPE_BOOLEAN:
7491 for (i = 0; i < alen; i++) {
7492 MonoBoolean val = *p++;
7493 mono_array_set (arr, MonoBoolean, i, val);
7496 case MONO_TYPE_CHAR:
7499 for (i = 0; i < alen; i++) {
7500 guint16 val = read16 (p);
7501 mono_array_set (arr, guint16, i, val);
7508 for (i = 0; i < alen; i++) {
7509 guint32 val = read32 (p);
7510 mono_array_set (arr, guint32, i, val);
7515 for (i = 0; i < alen; i++) {
7518 mono_array_set (arr, double, i, val);
7524 for (i = 0; i < alen; i++) {
7525 guint64 val = read64 (p);
7526 mono_array_set (arr, guint64, i, val);
7530 case MONO_TYPE_CLASS:
7531 case MONO_TYPE_OBJECT:
7532 case MONO_TYPE_STRING:
7533 for (i = 0; i < alen; i++) {
7534 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7535 mono_array_setref (arr, i, item);
7539 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7545 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7551 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7553 static MonoClass *klass;
7554 static MonoMethod *ctor;
7556 void *params [2], *unboxed;
7559 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7561 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7563 params [0] = mono_type_get_object (mono_domain_get (), t);
7565 retval = mono_object_new (mono_domain_get (), klass);
7566 unboxed = mono_object_unbox (retval);
7567 mono_runtime_invoke (ctor, unboxed, params, NULL);
7573 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7575 static MonoClass *klass;
7576 static MonoMethod *ctor;
7578 void *unboxed, *params [2];
7581 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7583 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7586 params [1] = typedarg;
7587 retval = mono_object_new (mono_domain_get (), klass);
7588 unboxed = mono_object_unbox (retval);
7589 mono_runtime_invoke (ctor, unboxed, params, NULL);
7595 type_is_reference (MonoType *type)
7597 switch (type->type) {
7598 case MONO_TYPE_BOOLEAN:
7599 case MONO_TYPE_CHAR:
7612 case MONO_TYPE_VALUETYPE:
7620 free_param_data (MonoMethodSignature *sig, void **params) {
7622 for (i = 0; i < sig->param_count; ++i) {
7623 if (!type_is_reference (sig->params [i]))
7624 g_free (params [i]);
7629 * Find the field index in the metadata FieldDef table.
7632 find_field_index (MonoClass *klass, MonoClassField *field) {
7635 for (i = 0; i < klass->field.count; ++i) {
7636 if (field == &klass->fields [i])
7637 return klass->field.first + 1 + i;
7643 * Find the property index in the metadata Property table.
7646 find_property_index (MonoClass *klass, MonoProperty *property) {
7649 for (i = 0; i < klass->property.count; ++i) {
7650 if (property == &klass->properties [i])
7651 return klass->property.first + 1 + i;
7657 * Find the event index in the metadata Event table.
7660 find_event_index (MonoClass *klass, MonoEvent *event) {
7663 for (i = 0; i < klass->event.count; ++i) {
7664 if (event == &klass->events [i])
7665 return klass->event.first + 1 + i;
7671 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7673 const char *p = (const char*)data;
7675 guint32 i, j, num_named;
7679 mono_class_init (method->klass);
7682 attr = mono_object_new (mono_domain_get (), method->klass);
7683 mono_runtime_invoke (method, attr, NULL, NULL);
7687 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7690 /*g_print ("got attr %s\n", method->klass->name);*/
7692 /* Allocate using alloca so it gets GC tracking */
7693 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7697 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7698 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7702 attr = mono_object_new (mono_domain_get (), method->klass);
7703 mono_runtime_invoke (method, attr, params, NULL);
7704 free_param_data (method->signature, params);
7705 num_named = read16 (named);
7707 for (j = 0; j < num_named; j++) {
7709 char *name, named_type, data_type;
7710 named_type = *named++;
7711 data_type = *named++; /* type of data */
7712 if (data_type == MONO_TYPE_SZARRAY)
7713 data_type = *named++;
7714 if (data_type == MONO_TYPE_ENUM) {
7717 type_len = mono_metadata_decode_blob_size (named, &named);
7718 type_name = g_malloc (type_len + 1);
7719 memcpy (type_name, named, type_len);
7720 type_name [type_len] = 0;
7722 /* FIXME: lookup the type and check type consistency */
7725 name_len = mono_metadata_decode_blob_size (named, &named);
7726 name = g_malloc (name_len + 1);
7727 memcpy (name, named, name_len);
7728 name [name_len] = 0;
7730 if (named_type == 0x53) {
7731 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7732 void *val = load_cattr_value (image, field->type, named, &named);
7733 mono_field_set_value (attr, field, val);
7734 if (!type_is_reference (field->type))
7736 } else if (named_type == 0x54) {
7739 MonoType *prop_type;
7741 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7742 /* can we have more that 1 arg in a custom attr named property? */
7743 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7744 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7745 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7746 mono_property_set_value (prop, attr, pparams, NULL);
7747 if (!type_is_reference (prop_type))
7748 g_free (pparams [0]);
7757 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7759 MonoArray *typedargs, *namedargs;
7760 MonoClass *attrklass;
7761 static MonoMethod *ctor;
7764 const char *p = (const char*)data;
7766 guint32 i, j, num_named;
7769 mono_class_init (method->klass);
7772 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7774 domain = mono_domain_get ();
7776 /* This is for Attributes with no parameters */
7777 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7778 params [0] = mono_method_get_object (domain, method, NULL);
7779 params [1] = params [2] = NULL;
7780 mono_runtime_invoke (method, attr, params, NULL);
7784 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7787 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7791 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7792 MonoObject *obj, *typedarg;
7795 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7796 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7797 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7798 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7799 mono_array_setref (typedargs, i, typedarg);
7801 if (!type_is_reference (mono_method_signature (method)->params [i]))
7806 num_named = read16 (named);
7807 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7809 attrklass = method->klass;
7810 for (j = 0; j < num_named; j++) {
7812 char *name, named_type, data_type;
7813 named_type = *named++;
7814 data_type = *named++; /* type of data */
7815 if (data_type == MONO_TYPE_SZARRAY)
7816 data_type = *named++;
7817 if (data_type == MONO_TYPE_ENUM) {
7820 type_len = mono_metadata_decode_blob_size (named, &named);
7821 type_name = g_malloc (type_len + 1);
7822 memcpy (type_name, named, type_len);
7823 type_name [type_len] = 0;
7825 /* FIXME: lookup the type and check type consistency */
7828 name_len = mono_metadata_decode_blob_size (named, &named);
7829 name = g_malloc (name_len + 1);
7830 memcpy (name, named, name_len);
7831 name [name_len] = 0;
7833 if (named_type == 0x53) {
7834 MonoObject *obj, *typedarg, *namedarg;
7835 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7836 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7838 minfo = mono_field_get_object (domain, NULL, field);
7839 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7840 typedarg = create_cattr_typed_arg (field->type, obj);
7841 namedarg = create_cattr_named_arg (minfo, typedarg);
7842 mono_array_setref (namedargs, j, namedarg);
7843 if (!type_is_reference (field->type))
7845 } else if (named_type == 0x54) {
7846 MonoObject *obj, *typedarg, *namedarg;
7847 MonoType *prop_type;
7849 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7851 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7852 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7853 minfo = mono_property_get_object (domain, NULL, prop);
7854 val = load_cattr_value (image, prop_type, named, &named);
7855 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7856 typedarg = create_cattr_typed_arg (prop_type, obj);
7857 namedarg = create_cattr_named_arg (minfo, typedarg);
7858 mono_array_setref (namedargs, j, namedarg);
7859 if (!type_is_reference (prop_type))
7864 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7865 params [0] = mono_method_get_object (domain, method, NULL);
7866 params [1] = typedargs;
7867 params [2] = namedargs;
7868 mono_runtime_invoke (ctor, attr, params, NULL);
7873 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7879 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7880 for (i = 0; i < cinfo->num_attrs; ++i) {
7881 if (!cinfo->attrs [i].ctor)
7882 /* The cattr type is not finished yet */
7883 /* We should include the type name but cinfo doesn't contain it */
7884 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7885 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7886 mono_array_setref (result, i, attr);
7892 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7899 for (i = 0; i < cinfo->num_attrs; ++i) {
7900 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7904 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7906 for (i = 0; i < cinfo->num_attrs; ++i) {
7907 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7908 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7909 mono_array_setref (result, n, attr);
7917 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7923 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7924 for (i = 0; i < cinfo->num_attrs; ++i) {
7925 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7926 mono_array_setref (result, i, attr);
7932 * mono_custom_attrs_from_index:
7934 * Returns: NULL if no attributes are found or if a loading error occurs.
7937 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7939 guint32 mtoken, i, len;
7940 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7942 MonoCustomAttrInfo *ainfo;
7943 GList *tmp, *list = NULL;
7946 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7948 i = mono_metadata_custom_attrs_from_index (image, idx);
7952 while (i < ca->rows) {
7953 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7955 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7958 len = g_list_length (list);
7961 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7962 ainfo->num_attrs = len;
7963 ainfo->image = image;
7964 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7965 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7966 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7967 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7968 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7969 mtoken |= MONO_TOKEN_METHOD_DEF;
7971 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7972 mtoken |= MONO_TOKEN_MEMBER_REF;
7975 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7978 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7979 if (!ainfo->attrs [i].ctor) {
7980 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7985 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7986 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7987 ainfo->attrs [i].data = (guchar*)data;
7995 mono_custom_attrs_from_method (MonoMethod *method)
8000 * An instantiated method has the same cattrs as the generic method definition.
8002 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8003 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8005 if (method->is_inflated)
8006 method = ((MonoMethodInflated *) method)->declaring;
8008 if (method->dynamic || method->klass->image->dynamic)
8009 return lookup_custom_attr (method->klass->image, method);
8011 idx = mono_method_get_index (method);
8012 idx <<= MONO_CUSTOM_ATTR_BITS;
8013 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8014 return mono_custom_attrs_from_index (method->klass->image, idx);
8018 mono_custom_attrs_from_class (MonoClass *klass)
8022 if (klass->generic_class)
8023 klass = klass->generic_class->container_class;
8025 if (klass->image->dynamic)
8026 return lookup_custom_attr (klass->image, klass);
8028 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8029 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8030 idx <<= MONO_CUSTOM_ATTR_BITS;
8031 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8033 idx = mono_metadata_token_index (klass->type_token);
8034 idx <<= MONO_CUSTOM_ATTR_BITS;
8035 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8037 return mono_custom_attrs_from_index (klass->image, idx);
8041 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8045 if (assembly->image->dynamic)
8046 return lookup_custom_attr (assembly->image, assembly);
8047 idx = 1; /* there is only one assembly */
8048 idx <<= MONO_CUSTOM_ATTR_BITS;
8049 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8050 return mono_custom_attrs_from_index (assembly->image, idx);
8053 static MonoCustomAttrInfo*
8054 mono_custom_attrs_from_module (MonoImage *image)
8059 return lookup_custom_attr (image, image);
8060 idx = 1; /* there is only one module */
8061 idx <<= MONO_CUSTOM_ATTR_BITS;
8062 idx |= MONO_CUSTOM_ATTR_MODULE;
8063 return mono_custom_attrs_from_index (image, idx);
8067 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8071 if (klass->image->dynamic) {
8072 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8073 return lookup_custom_attr (klass->image, property);
8075 idx = find_property_index (klass, property);
8076 idx <<= MONO_CUSTOM_ATTR_BITS;
8077 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8078 return mono_custom_attrs_from_index (klass->image, idx);
8082 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8086 if (klass->image->dynamic) {
8087 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8088 return lookup_custom_attr (klass->image, event);
8090 idx = find_event_index (klass, event);
8091 idx <<= MONO_CUSTOM_ATTR_BITS;
8092 idx |= MONO_CUSTOM_ATTR_EVENT;
8093 return mono_custom_attrs_from_index (klass->image, idx);
8097 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8100 if (klass->image->dynamic) {
8101 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8102 return lookup_custom_attr (klass->image, field);
8104 idx = find_field_index (klass, field);
8105 idx <<= MONO_CUSTOM_ATTR_BITS;
8106 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8107 return mono_custom_attrs_from_index (klass->image, idx);
8111 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8114 guint32 i, idx, method_index;
8115 guint32 param_list, param_last, param_pos, found;
8117 MonoReflectionMethodAux *aux;
8120 * An instantiated method has the same cattrs as the generic method definition.
8122 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8123 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8125 if (method->is_inflated)
8126 method = ((MonoMethodInflated *) method)->declaring;
8128 if (method->klass->image->dynamic) {
8129 MonoCustomAttrInfo *res, *ainfo;
8132 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8133 if (!aux || !aux->param_cattr)
8136 /* Need to copy since it will be freed later */
8137 ainfo = aux->param_cattr [param];
8138 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
8139 res = g_malloc0 (size);
8140 memcpy (res, ainfo, size);
8144 image = method->klass->image;
8145 method_index = mono_method_get_index (method);
8146 ca = &image->tables [MONO_TABLE_METHOD];
8148 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8149 if (method_index == ca->rows) {
8150 ca = &image->tables [MONO_TABLE_PARAM];
8151 param_last = ca->rows + 1;
8153 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8154 ca = &image->tables [MONO_TABLE_PARAM];
8157 for (i = param_list; i < param_last; ++i) {
8158 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8159 if (param_pos == param) {
8167 idx <<= MONO_CUSTOM_ATTR_BITS;
8168 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8169 return mono_custom_attrs_from_index (image, idx);
8173 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8177 for (i = 0; i < ainfo->num_attrs; ++i) {
8178 klass = ainfo->attrs [i].ctor->klass;
8179 if (mono_class_has_parent (klass, attr_klass))
8186 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8193 for (i = 0; i < ainfo->num_attrs; ++i) {
8194 klass = ainfo->attrs [i].ctor->klass;
8195 if (mono_class_has_parent (klass, attr_klass)) {
8200 if (attr_index == -1)
8203 attrs = mono_custom_attrs_construct (ainfo);
8205 return mono_array_get (attrs, MonoObject*, attr_index);
8211 * mono_reflection_get_custom_attrs_info:
8212 * @obj: a reflection object handle
8214 * Return the custom attribute info for attributes defined for the
8215 * reflection handle @obj. The objects.
8218 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8221 MonoCustomAttrInfo *cinfo = NULL;
8223 klass = obj->vtable->klass;
8224 if (klass == mono_defaults.monotype_class) {
8225 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8226 klass = mono_class_from_mono_type (rtype->type);
8227 cinfo = mono_custom_attrs_from_class (klass);
8228 } else if (strcmp ("Assembly", klass->name) == 0) {
8229 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8230 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8231 } else if (strcmp ("Module", klass->name) == 0) {
8232 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8233 cinfo = mono_custom_attrs_from_module (module->image);
8234 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8235 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8236 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8237 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8238 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
8239 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8240 } else if (strcmp ("MonoField", klass->name) == 0) {
8241 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8242 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8243 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8244 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8245 cinfo = mono_custom_attrs_from_method (rmethod->method);
8246 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8247 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8248 cinfo = mono_custom_attrs_from_method (rmethod->method);
8249 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8250 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8251 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8252 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8253 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8254 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8255 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8256 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8257 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8258 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8259 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8260 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8261 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8262 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8263 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8264 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8265 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8266 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8267 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8268 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8269 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8270 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8271 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8272 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8273 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8274 } else { /* handle other types here... */
8275 g_error ("get custom attrs not yet supported for %s", klass->name);
8282 * mono_reflection_get_custom_attrs_by_type:
8283 * @obj: a reflection object handle
8285 * Return an array with all the custom attributes defined of the
8286 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8287 * of that type are returned. The objects are fully build. Return NULL if a loading error
8291 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8294 MonoCustomAttrInfo *cinfo;
8296 cinfo = mono_reflection_get_custom_attrs_info (obj);
8299 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8301 result = mono_custom_attrs_construct (cinfo);
8303 mono_custom_attrs_free (cinfo);
8305 if (mono_loader_get_last_error ())
8307 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8314 * mono_reflection_get_custom_attrs:
8315 * @obj: a reflection object handle
8317 * Return an array with all the custom attributes defined of the
8318 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8322 mono_reflection_get_custom_attrs (MonoObject *obj)
8324 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8328 * mono_reflection_get_custom_attrs_data:
8329 * @obj: a reflection obj handle
8331 * Returns an array of System.Reflection.CustomAttributeData,
8332 * which include information about attributes reflected on
8333 * types loaded using the Reflection Only methods
8336 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8339 MonoCustomAttrInfo *cinfo;
8341 cinfo = mono_reflection_get_custom_attrs_info (obj);
8343 result = mono_custom_attrs_data_construct (cinfo);
8345 mono_custom_attrs_free (cinfo);
8347 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8352 static MonoReflectionType*
8353 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8355 MonoMethod *method_get_underlying_system_type;
8357 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8358 mono_class_get_method_from_name (mono_object_class (t),
8359 "get_UnderlyingSystemType",
8361 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8365 mono_reflection_type_get_handle (MonoReflectionType* t)
8370 t = mono_reflection_type_get_underlying_system_type (t);
8378 * LOCKING: Assumes the loader lock is held.
8380 static MonoMethodSignature*
8381 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
8382 MonoMethodSignature *sig;
8385 count = parameters? mono_array_length (parameters): 0;
8387 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8388 sig->param_count = count;
8389 sig->sentinelpos = -1; /* FIXME */
8390 for (i = 0; i < count; ++i) {
8391 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8392 sig->params [i] = mono_reflection_type_get_handle (pt);
8398 * LOCKING: Assumes the loader lock is held.
8400 static MonoMethodSignature*
8401 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
8402 MonoMethodSignature *sig;
8404 sig = parameters_to_signature (mp, ctor->parameters);
8405 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8406 sig->ret = &mono_defaults.void_class->byval_arg;
8411 * LOCKING: Assumes the loader lock is held.
8413 static MonoMethodSignature*
8414 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
8415 MonoMethodSignature *sig;
8417 sig = parameters_to_signature (mp, method->parameters);
8418 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8419 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8420 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8424 static MonoMethodSignature*
8425 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8426 MonoMethodSignature *sig;
8428 sig = parameters_to_signature (NULL, method->parameters);
8429 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8430 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8431 sig->generic_param_count = 0;
8436 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8438 MonoClass *klass = mono_object_class (prop);
8439 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8440 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8441 *name = mono_string_to_utf8 (pb->name);
8442 *type = pb->type->type;
8444 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8445 *name = g_strdup (p->property->name);
8446 if (p->property->get)
8447 *type = mono_method_signature (p->property->get)->ret;
8449 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8454 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8456 MonoClass *klass = mono_object_class (field);
8457 if (strcmp (klass->name, "FieldBuilder") == 0) {
8458 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8459 *name = mono_string_to_utf8 (fb->name);
8460 *type = fb->type->type;
8462 MonoReflectionField *f = (MonoReflectionField *)field;
8463 *name = g_strdup (mono_field_get_name (f->field));
8464 *type = f->field->type;
8469 * Encode a value in a custom attribute stream of bytes.
8470 * The value to encode is either supplied as an object in argument val
8471 * (valuetypes are boxed), or as a pointer to the data in the
8473 * @type represents the type of the value
8474 * @buffer is the start of the buffer
8475 * @p the current position in the buffer
8476 * @buflen contains the size of the buffer and is used to return the new buffer size
8477 * if this needs to be realloced.
8478 * @retbuffer and @retp return the start and the position of the buffer
8481 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8483 MonoTypeEnum simple_type;
8485 if ((p-buffer) + 10 >= *buflen) {
8488 newbuf = g_realloc (buffer, *buflen);
8489 p = newbuf + (p-buffer);
8493 argval = ((char*)arg + sizeof (MonoObject));
8494 simple_type = type->type;
8496 switch (simple_type) {
8497 case MONO_TYPE_BOOLEAN:
8502 case MONO_TYPE_CHAR:
8505 swap_with_size (p, argval, 2, 1);
8511 swap_with_size (p, argval, 4, 1);
8515 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8525 swap_with_size (p, argval, 8, 1);
8531 swap_with_size (p, argval, 8, 1);
8534 case MONO_TYPE_VALUETYPE:
8535 if (type->data.klass->enumtype) {
8536 simple_type = type->data.klass->enum_basetype->type;
8539 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8542 case MONO_TYPE_STRING: {
8549 str = mono_string_to_utf8 ((MonoString*)arg);
8550 slen = strlen (str);
8551 if ((p-buffer) + 10 + slen >= *buflen) {
8555 newbuf = g_realloc (buffer, *buflen);
8556 p = newbuf + (p-buffer);
8559 mono_metadata_encode_value (slen, p, &p);
8560 memcpy (p, str, slen);
8565 case MONO_TYPE_CLASS: {
8573 k = mono_object_class (arg);
8574 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8575 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8576 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8579 if (rt && (rtc = mono_object_class (rt)) &&
8580 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8581 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8582 arg = (MonoObject *) rt;
8585 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8588 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8589 slen = strlen (str);
8590 if ((p-buffer) + 10 + slen >= *buflen) {
8594 newbuf = g_realloc (buffer, *buflen);
8595 p = newbuf + (p-buffer);
8598 mono_metadata_encode_value (slen, p, &p);
8599 memcpy (p, str, slen);
8604 case MONO_TYPE_SZARRAY: {
8606 MonoClass *eclass, *arg_eclass;
8609 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8612 len = mono_array_length ((MonoArray*)arg);
8614 *p++ = (len >> 8) & 0xff;
8615 *p++ = (len >> 16) & 0xff;
8616 *p++ = (len >> 24) & 0xff;
8618 *retbuffer = buffer;
8619 eclass = type->data.klass;
8620 arg_eclass = mono_object_class (arg)->element_class;
8623 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8624 eclass = mono_defaults.object_class;
8626 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8627 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8628 int elsize = mono_class_array_element_size (arg_eclass);
8629 for (i = 0; i < len; ++i) {
8630 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8633 } else if (eclass->valuetype && arg_eclass->valuetype) {
8634 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8635 int elsize = mono_class_array_element_size (eclass);
8636 for (i = 0; i < len; ++i) {
8637 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8641 for (i = 0; i < len; ++i) {
8642 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8647 case MONO_TYPE_OBJECT: {
8653 * The parameter type is 'object' but the type of the actual
8654 * argument is not. So we have to add type information to the blob
8655 * too. This is completely undocumented in the spec.
8659 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8664 klass = mono_object_class (arg);
8666 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8669 } else if (klass->enumtype) {
8671 } else if (klass == mono_defaults.string_class) {
8672 simple_type = MONO_TYPE_STRING;
8675 } else if (klass->rank == 1) {
8677 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8678 /* See Partition II, Appendix B3 */
8681 *p++ = klass->element_class->byval_arg.type;
8682 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8684 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8685 *p++ = simple_type = klass->byval_arg.type;
8688 g_error ("unhandled type in custom attr");
8690 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8691 slen = strlen (str);
8692 if ((p-buffer) + 10 + slen >= *buflen) {
8696 newbuf = g_realloc (buffer, *buflen);
8697 p = newbuf + (p-buffer);
8700 mono_metadata_encode_value (slen, p, &p);
8701 memcpy (p, str, slen);
8704 simple_type = klass->enum_basetype->type;
8708 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8711 *retbuffer = buffer;
8715 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8717 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8718 char *str = type_get_qualified_name (type, NULL);
8719 int slen = strlen (str);
8723 * This seems to be optional...
8726 mono_metadata_encode_value (slen, p, &p);
8727 memcpy (p, str, slen);
8730 } else if (type->type == MONO_TYPE_OBJECT) {
8732 } else if (type->type == MONO_TYPE_CLASS) {
8733 /* it should be a type: encode_cattr_value () has the check */
8736 mono_metadata_encode_value (type->type, p, &p);
8737 if (type->type == MONO_TYPE_SZARRAY)
8738 /* See the examples in Partition VI, Annex B */
8739 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8746 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8749 /* Preallocate a large enough buffer */
8750 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8751 char *str = type_get_qualified_name (type, NULL);
8754 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8755 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8761 len += strlen (name);
8763 if ((p-buffer) + 20 + len >= *buflen) {
8767 newbuf = g_realloc (buffer, *buflen);
8768 p = newbuf + (p-buffer);
8772 encode_field_or_prop_type (type, p, &p);
8774 len = strlen (name);
8775 mono_metadata_encode_value (len, p, &p);
8776 memcpy (p, name, len);
8778 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8780 *retbuffer = buffer;
8783 #ifndef DISABLE_REFLECTION_EMIT
8786 * mono_reflection_get_custom_attrs_blob:
8787 * @ctor: custom attribute constructor
8788 * @ctorArgs: arguments o the constructor
8794 * Creates the blob of data that needs to be saved in the metadata and that represents
8795 * the custom attributed described by @ctor, @ctorArgs etc.
8796 * Returns: a Byte array representing the blob of data.
8799 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8802 MonoMethodSignature *sig;
8807 MONO_ARCH_SAVE_REGS;
8809 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8810 /* sig is freed later so allocate it in the heap */
8811 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8813 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8816 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8818 p = buffer = g_malloc (buflen);
8819 /* write the prolog */
8822 for (i = 0; i < sig->param_count; ++i) {
8823 arg = mono_array_get (ctorArgs, MonoObject*, i);
8824 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8828 i += mono_array_length (properties);
8830 i += mono_array_length (fields);
8832 *p++ = (i >> 8) & 0xff;
8835 for (i = 0; i < mono_array_length (properties); ++i) {
8839 prop = mono_array_get (properties, gpointer, i);
8840 get_prop_name_and_type (prop, &pname, &ptype);
8841 *p++ = 0x54; /* PROPERTY signature */
8842 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8849 for (i = 0; i < mono_array_length (fields); ++i) {
8853 field = mono_array_get (fields, gpointer, i);
8854 get_field_name_and_type (field, &fname, &ftype);
8855 *p++ = 0x53; /* FIELD signature */
8856 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8861 g_assert (p - buffer <= buflen);
8862 buflen = p - buffer;
8863 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8864 p = mono_array_addr (result, char, 0);
8865 memcpy (p, buffer, buflen);
8867 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8873 * mono_reflection_setup_internal_class:
8874 * @tb: a TypeBuilder object
8876 * Creates a MonoClass that represents the TypeBuilder.
8877 * This is a trick that lets us simplify a lot of reflection code
8878 * (and will allow us to support Build and Run assemblies easier).
8881 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8883 MonoClass *klass, *parent;
8885 MONO_ARCH_SAVE_REGS;
8887 mono_loader_lock ();
8890 /* check so we can compile corlib correctly */
8891 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8892 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8893 parent = tb->parent->type->data.klass;
8895 parent = my_mono_class_from_mono_type (tb->parent->type);
8901 /* the type has already being created: it means we just have to change the parent */
8902 if (tb->type.type) {
8903 klass = mono_class_from_mono_type (tb->type.type);
8904 klass->parent = NULL;
8905 /* fool mono_class_setup_parent */
8906 klass->supertypes = NULL;
8907 mono_class_setup_parent (klass, parent);
8908 mono_class_setup_mono_type (klass);
8909 mono_loader_unlock ();
8913 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
8915 klass->image = &tb->module->dynamic_image->image;
8917 klass->inited = 1; /* we lie to the runtime */
8918 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8919 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8920 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8921 klass->flags = tb->attrs;
8923 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8925 klass->element_class = klass;
8927 MOVING_GC_REGISTER (&klass->reflection_info);
8928 klass->reflection_info = tb;
8930 /* Put into cache so mono_class_get () will find it */
8931 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8933 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8934 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8936 if (parent != NULL) {
8937 mono_class_setup_parent (klass, parent);
8938 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8939 const char *old_n = klass->name;
8940 /* trick to get relative numbering right when compiling corlib */
8941 klass->name = "BuildingObject";
8942 mono_class_setup_parent (klass, mono_defaults.object_class);
8943 klass->name = old_n;
8946 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8947 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8948 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8949 klass->instance_size = sizeof (MonoObject);
8950 klass->size_inited = 1;
8951 mono_class_setup_vtable_general (klass, NULL, 0);
8954 mono_class_setup_mono_type (klass);
8956 mono_class_setup_supertypes (klass);
8959 * FIXME: handle interfaces.
8962 tb->type.type = &klass->byval_arg;
8964 if (tb->nesting_type) {
8965 g_assert (tb->nesting_type->type);
8966 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8969 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8971 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8973 mono_loader_unlock ();
8977 * mono_reflection_setup_generic_class:
8978 * @tb: a TypeBuilder object
8980 * Setup the generic class before adding the first generic parameter.
8983 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8988 * mono_reflection_create_generic_class:
8989 * @tb: a TypeBuilder object
8991 * Creates the generic class after all generic parameters have been added.
8994 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8999 MONO_ARCH_SAVE_REGS;
9001 klass = my_mono_class_from_mono_type (tb->type.type);
9003 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9005 if (klass->generic_container || (count == 0))
9008 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9010 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9012 klass->generic_container->owner.klass = klass;
9013 klass->generic_container->type_argc = count;
9014 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParam) * count);
9016 for (i = 0; i < count; i++) {
9017 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9018 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
9019 /*Make sure we are a diferent type instance */
9020 klass->generic_container->type_params [i].owner = klass->generic_container;
9021 klass->generic_container->type_params [i].pklass = NULL;
9023 g_assert (klass->generic_container->type_params [i].owner);
9026 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9030 * mono_reflection_create_internal_class:
9031 * @tb: a TypeBuilder object
9033 * Actually create the MonoClass that is associated with the TypeBuilder.
9036 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9040 MONO_ARCH_SAVE_REGS;
9042 klass = my_mono_class_from_mono_type (tb->type.type);
9044 mono_loader_lock ();
9045 if (klass->enumtype && klass->enum_basetype == NULL) {
9046 MonoReflectionFieldBuilder *fb;
9049 g_assert (tb->fields != NULL);
9050 g_assert (mono_array_length (tb->fields) >= 1);
9052 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9054 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
9055 mono_loader_unlock ();
9059 klass->enum_basetype = fb->type->type;
9060 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
9061 if (!klass->element_class)
9062 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
9065 * get the element_class from the current corlib.
9067 ec = default_class_from_mono_type (klass->enum_basetype);
9068 klass->instance_size = ec->instance_size;
9069 klass->size_inited = 1;
9071 * this is almost safe to do with enums and it's needed to be able
9072 * to create objects of the enum type (for use in SetConstant).
9074 /* FIXME: Does this mean enums can't have method overrides ? */
9075 mono_class_setup_vtable_general (klass, NULL, 0);
9077 mono_loader_unlock ();
9080 #endif /* DISABLE_REFLECTION_EMIT */
9082 static MonoMarshalSpec*
9083 mono_marshal_spec_from_builder (MonoMemPool *mp, MonoAssembly *assembly,
9084 MonoReflectionMarshal *minfo)
9086 MonoMarshalSpec *res;
9088 res = mp_g_new0 (mp, MonoMarshalSpec, 1);
9089 res->native = minfo->type;
9091 switch (minfo->type) {
9092 case MONO_NATIVE_LPARRAY:
9093 res->data.array_data.elem_type = minfo->eltype;
9094 if (minfo->has_size) {
9095 res->data.array_data.param_num = minfo->param_num;
9096 res->data.array_data.num_elem = minfo->count;
9097 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9100 res->data.array_data.param_num = -1;
9101 res->data.array_data.num_elem = -1;
9102 res->data.array_data.elem_mult = -1;
9106 case MONO_NATIVE_BYVALTSTR:
9107 case MONO_NATIVE_BYVALARRAY:
9108 res->data.array_data.num_elem = minfo->count;
9111 case MONO_NATIVE_CUSTOM:
9112 if (minfo->marshaltyperef)
9113 res->data.custom_data.custom_name =
9114 type_get_fully_qualified_name (minfo->marshaltyperef->type);
9116 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9126 MonoReflectionMarshal*
9127 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9128 MonoMarshalSpec *spec)
9130 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9131 MonoReflectionMarshal *minfo;
9134 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9135 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9136 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9137 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9140 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9141 minfo->type = spec->native;
9143 switch (minfo->type) {
9144 case MONO_NATIVE_LPARRAY:
9145 minfo->eltype = spec->data.array_data.elem_type;
9146 minfo->count = spec->data.array_data.num_elem;
9147 minfo->param_num = spec->data.array_data.param_num;
9150 case MONO_NATIVE_BYVALTSTR:
9151 case MONO_NATIVE_BYVALARRAY:
9152 minfo->count = spec->data.array_data.num_elem;
9155 case MONO_NATIVE_CUSTOM:
9156 if (spec->data.custom_data.custom_name) {
9157 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9159 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9161 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9163 if (spec->data.custom_data.cookie)
9164 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9175 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9176 ReflectionMethodBuilder *rmb,
9177 MonoMethodSignature *sig)
9180 MonoMethodNormal *pm;
9181 MonoMarshalSpec **specs;
9182 MonoReflectionMethodAux *method_aux;
9188 * Methods created using a MethodBuilder should have their memory allocated
9189 * inside the image mempool, while dynamic methods should have their memory
9192 dynamic = rmb->refs != NULL;
9193 mp = dynamic ? NULL : klass->image->mempool;
9196 g_assert (!klass->generic_class);
9198 mono_loader_lock ();
9200 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9201 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9202 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
9204 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
9206 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
9208 pm = (MonoMethodNormal*)m;
9210 m->dynamic = dynamic;
9212 m->flags = rmb->attrs;
9213 m->iflags = rmb->iattrs;
9214 m->name = mp_string_to_utf8 (mp, rmb->name);
9217 m->skip_visibility = rmb->skip_visibility;
9219 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9221 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9222 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9225 m->signature->pinvoke = 1;
9226 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9227 m->signature->pinvoke = 1;
9229 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9231 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
9232 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
9234 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9236 if (klass->image->dynamic)
9237 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9239 mono_loader_unlock ();
9242 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9243 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9244 MonoMethodHeader *header;
9246 gint32 max_stack, i;
9247 gint32 num_locals = 0;
9248 gint32 num_clauses = 0;
9252 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9253 code_size = rmb->ilgen->code_len;
9254 max_stack = rmb->ilgen->max_stack;
9255 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9256 if (rmb->ilgen->ex_handlers)
9257 num_clauses = method_count_clauses (rmb->ilgen);
9260 code = mono_array_addr (rmb->code, guint8, 0);
9261 code_size = mono_array_length (rmb->code);
9262 /* we probably need to run a verifier on the code... */
9272 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
9273 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9274 header->code_size = code_size;
9275 header->code = mp_g_malloc (mp, code_size);
9276 memcpy ((char*)header->code, code, code_size);
9277 header->max_stack = max_stack;
9278 header->init_locals = rmb->init_locals;
9279 header->num_locals = num_locals;
9281 for (i = 0; i < num_locals; ++i) {
9282 MonoReflectionLocalBuilder *lb =
9283 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9285 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
9286 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9289 header->num_clauses = num_clauses;
9291 header->clauses = method_encode_clauses (mp, (MonoDynamicImage*)klass->image,
9292 rmb->ilgen, num_clauses);
9295 pm->header = header;
9298 if (rmb->generic_params) {
9299 int count = mono_array_length (rmb->generic_params);
9300 MonoGenericContainer *container;
9302 container = rmb->generic_container;
9304 m->is_generic = TRUE;
9305 mono_method_set_generic_container (m, container);
9307 container->type_argc = count;
9308 container->type_params = mp_g_new0 (mp, MonoGenericParam, count);
9309 container->owner.method = m;
9311 for (i = 0; i < count; i++) {
9312 MonoReflectionGenericParam *gp =
9313 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9315 container->type_params [i] = *gp->type.type->data.generic_param;
9318 if (klass->generic_container) {
9319 container->parent = klass->generic_container;
9320 container->context.class_inst = klass->generic_container->context.class_inst;
9322 container->context.method_inst = mono_get_shared_generic_inst (container);
9326 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9330 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9332 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
9333 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9334 for (i = 0; i < rmb->nrefs; ++i)
9335 data [i + 1] = rmb->refs [i];
9340 /* Parameter info */
9343 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9344 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
9345 for (i = 0; i <= m->signature->param_count; ++i) {
9346 MonoReflectionParamBuilder *pb;
9347 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9348 if ((i > 0) && (pb->attrs)) {
9349 /* Make a copy since it might point to a shared type structure */
9350 m->signature->params [i - 1] = mono_metadata_type_dup (mp, m->signature->params [i - 1]);
9351 m->signature->params [i - 1]->attrs = pb->attrs;
9354 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9355 MonoDynamicImage *assembly;
9356 guint32 idx, def_type, len;
9360 if (!method_aux->param_defaults) {
9361 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
9362 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
9364 assembly = (MonoDynamicImage*)klass->image;
9365 idx = encode_constant (assembly, pb->def_value, &def_type);
9366 /* Copy the data from the blob since it might get realloc-ed */
9367 p = assembly->blob.data + idx;
9368 len = mono_metadata_decode_blob_size (p, &p2);
9370 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
9371 method_aux->param_default_types [i] = def_type;
9372 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9376 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
9378 if (!method_aux->param_cattr)
9379 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
9380 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (mp, klass->image, pb->cattrs);
9386 /* Parameter marshalling */
9389 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9390 MonoReflectionParamBuilder *pb;
9391 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9392 if (pb->marshal_info) {
9394 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
9395 specs [pb->position] =
9396 mono_marshal_spec_from_builder (mp, klass->image->assembly, pb->marshal_info);
9400 if (specs != NULL) {
9402 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9403 method_aux->param_marshall = specs;
9406 if (klass->image->dynamic && method_aux)
9407 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9409 mono_loader_unlock ();
9415 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9417 ReflectionMethodBuilder rmb;
9418 MonoMethodSignature *sig;
9420 mono_loader_lock ();
9421 sig = ctor_builder_to_signature (klass->image->mempool, mb);
9422 mono_loader_unlock ();
9424 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9426 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9427 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9429 /* If we are in a generic class, we might be called multiple times from inflate_method */
9430 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9431 /* ilgen is no longer needed */
9439 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9441 ReflectionMethodBuilder rmb;
9442 MonoMethodSignature *sig;
9444 mono_loader_lock ();
9445 sig = method_builder_to_signature (klass->image->mempool, mb);
9446 mono_loader_unlock ();
9448 reflection_methodbuilder_from_method_builder (&rmb, mb);
9450 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9451 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9453 /* If we are in a generic class, we might be called multiple times from inflate_method */
9454 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9455 /* ilgen is no longer needed */
9461 static MonoClassField*
9462 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9464 MonoClassField *field;
9467 field = g_new0 (MonoClassField, 1);
9469 field->name = mono_string_to_utf8 (fb->name);
9470 if (fb->attrs || fb->modreq || fb->modopt) {
9471 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9472 field->type->attrs = fb->attrs;
9474 g_assert (klass->image->dynamic);
9475 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9476 g_free (field->type);
9477 field->type = custom;
9479 field->type = fb->type->type;
9481 if (fb->offset != -1)
9482 field->offset = fb->offset;
9483 field->parent = klass;
9484 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9486 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9492 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9495 MonoReflectionTypeBuilder *tb = NULL;
9496 gboolean is_dynamic = FALSE;
9500 mono_loader_lock ();
9502 domain = mono_object_domain (type);
9504 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9505 tb = (MonoReflectionTypeBuilder *) type;
9508 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9509 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9511 tb = rgi->generic_type;
9515 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9516 if (tb && tb->generic_container)
9517 mono_reflection_create_generic_class (tb);
9519 klass = mono_class_from_mono_type (type->type);
9520 if (!klass->generic_container) {
9521 mono_loader_unlock ();
9525 if (klass->wastypebuilder) {
9526 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9531 mono_loader_unlock ();
9533 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9535 return &geninst->byval_arg;
9539 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9541 MonoGenericClass *gclass;
9542 MonoGenericInst *inst;
9544 g_assert (klass->generic_container);
9546 inst = mono_metadata_get_generic_inst (type_argc, types);
9547 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9549 return mono_generic_class_get_class (gclass);
9552 MonoReflectionMethod*
9553 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9556 MonoMethod *method, *inflated;
9557 MonoMethodInflated *imethod;
9558 MonoReflectionMethodBuilder *mb = NULL;
9559 MonoGenericContext tmp_context;
9560 MonoGenericInst *ginst;
9561 MonoType **type_argv;
9564 MONO_ARCH_SAVE_REGS;
9566 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9567 #ifndef DISABLE_REFLECTION_EMIT
9568 MonoReflectionTypeBuilder *tb;
9571 mb = (MonoReflectionMethodBuilder *) rmethod;
9572 tb = (MonoReflectionTypeBuilder *) mb->type;
9573 klass = mono_class_from_mono_type (tb->type.type);
9575 method = methodbuilder_to_mono_method (klass, mb);
9577 g_assert_not_reached ();
9581 method = rmethod->method;
9584 klass = method->klass;
9586 if (method->is_inflated)
9587 method = ((MonoMethodInflated *) method)->declaring;
9589 count = mono_method_signature (method)->generic_param_count;
9590 if (count != mono_array_length (types))
9593 type_argv = g_new0 (MonoType *, count);
9594 for (i = 0; i < count; i++) {
9595 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9596 type_argv [i] = garg->type;
9598 ginst = mono_metadata_get_generic_inst (count, type_argv);
9601 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9602 tmp_context.method_inst = ginst;
9604 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9605 imethod = (MonoMethodInflated *) inflated;
9607 if (method->klass->image->dynamic) {
9608 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9610 * This table maps metadata structures representing inflated methods/fields
9611 * to the reflection objects representing their generic definitions.
9613 mono_loader_lock ();
9614 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9615 mono_loader_unlock ();
9618 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9621 #ifndef DISABLE_REFLECTION_EMIT
9624 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9626 MonoMethodInflated *imethod;
9627 MonoGenericContext *context;
9631 * With generic code sharing the klass might not be inflated.
9632 * This can happen because classes inflated with their own
9633 * type arguments are "normalized" to the uninflated class.
9635 if (!klass->generic_class)
9638 context = mono_class_get_context (klass);
9640 if (klass->method.count) {
9641 /* Find the already created inflated method */
9642 for (i = 0; i < klass->method.count; ++i) {
9643 g_assert (klass->methods [i]->is_inflated);
9644 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9647 g_assert (i < klass->method.count);
9648 imethod = (MonoMethodInflated*)klass->methods [i];
9650 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9653 if (method->is_generic && method->klass->image->dynamic) {
9654 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9656 mono_loader_lock ();
9657 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9658 mono_loader_unlock ();
9660 return (MonoMethod *) imethod;
9664 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9669 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9671 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9672 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9673 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9675 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9676 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9677 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9678 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9679 method = ((MonoReflectionMethod *) obj)->method;
9681 method = NULL; /* prevent compiler warning */
9682 g_assert_not_reached ();
9685 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9688 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9690 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9691 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9694 MonoGenericClass *gclass;
9695 MonoDynamicGenericClass *dgclass;
9696 MonoClass *klass, *gklass;
9699 MONO_ARCH_SAVE_REGS;
9701 klass = mono_class_from_mono_type (type->type.type);
9702 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9703 gclass = type->type.type->data.generic_class;
9705 g_assert (gclass->is_dynamic);
9706 dgclass = (MonoDynamicGenericClass *) gclass;
9708 if (dgclass->initialized)
9711 gklass = gclass->container_class;
9712 mono_class_init (gklass);
9714 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9715 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9716 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9717 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9718 dgclass->count_events = events ? mono_array_length (events) : 0;
9720 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9721 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9722 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9723 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9724 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9725 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
9726 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
9728 for (i = 0; i < dgclass->count_methods; i++) {
9729 MonoObject *obj = mono_array_get (methods, gpointer, i);
9731 dgclass->methods [i] = inflate_method (type, obj);
9734 for (i = 0; i < dgclass->count_ctors; i++) {
9735 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9737 dgclass->ctors [i] = inflate_method (type, obj);
9740 for (i = 0; i < dgclass->count_fields; i++) {
9741 MonoObject *obj = mono_array_get (fields, gpointer, i);
9742 MonoClassField *field, *inflated_field = NULL;
9744 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9745 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9746 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9747 field = ((MonoReflectionField *) obj)->field;
9749 field = NULL; /* prevent compiler warning */
9750 g_assert_not_reached ();
9753 dgclass->fields [i] = *field;
9754 dgclass->fields [i].parent = klass;
9755 dgclass->fields [i].type = mono_class_inflate_generic_type (
9756 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9757 dgclass->field_generic_types [i] = field->type;
9758 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
9759 dgclass->field_objects [i] = obj;
9761 if (inflated_field) {
9762 g_free (inflated_field);
9764 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9768 for (i = 0; i < dgclass->count_properties; i++) {
9769 MonoObject *obj = mono_array_get (properties, gpointer, i);
9770 MonoProperty *property = &dgclass->properties [i];
9772 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9773 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9775 property->parent = klass;
9776 property->attrs = pb->attrs;
9777 property->name = mono_string_to_utf8 (pb->name);
9779 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9781 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9782 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9783 *property = *((MonoReflectionProperty *) obj)->property;
9784 property->name = g_strdup (property->name);
9787 property->get = inflate_mono_method (klass, property->get, NULL);
9789 property->set = inflate_mono_method (klass, property->set, NULL);
9791 g_assert_not_reached ();
9794 for (i = 0; i < dgclass->count_events; i++) {
9795 MonoObject *obj = mono_array_get (events, gpointer, i);
9796 MonoEvent *event = &dgclass->events [i];
9798 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9799 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9801 event->parent = klass;
9802 event->attrs = eb->attrs;
9803 event->name = mono_string_to_utf8 (eb->name);
9805 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9806 if (eb->remove_method)
9807 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9808 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9809 *event = *((MonoReflectionEvent *) obj)->event;
9810 event->name = g_strdup (event->name);
9813 event->add = inflate_mono_method (klass, event->add, NULL);
9815 event->remove = inflate_mono_method (klass, event->remove, NULL);
9817 g_assert_not_reached ();
9820 dgclass->initialized = TRUE;
9824 ensure_generic_class_runtime_vtable (MonoClass *klass)
9826 MonoClass *gklass = klass->generic_class->container_class;
9829 if (klass->wastypebuilder)
9832 ensure_runtime_vtable (gklass);
9834 klass->method.count = gklass->method.count;
9835 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
9837 for (i = 0; i < klass->method.count; i++) {
9838 klass->methods [i] = mono_class_inflate_generic_method_full (
9839 gklass->methods [i], klass, mono_class_get_context (klass));
9842 klass->interface_count = gklass->interface_count;
9843 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9844 for (i = 0; i < klass->interface_count; ++i) {
9845 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
9846 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
9847 mono_metadata_free_type (iface_type);
9849 ensure_runtime_vtable (klass->interfaces [i]);
9851 /*We can only finish with this klass once it's parent has as well*/
9852 if (gklass->wastypebuilder)
9853 klass->wastypebuilder = TRUE;
9858 ensure_runtime_vtable (MonoClass *klass)
9860 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9863 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
9866 ensure_runtime_vtable (klass->parent);
9869 num = tb->ctors? mono_array_length (tb->ctors): 0;
9870 num += tb->num_methods;
9871 klass->method.count = num;
9872 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
9873 num = tb->ctors? mono_array_length (tb->ctors): 0;
9874 for (i = 0; i < num; ++i)
9875 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9876 num = tb->num_methods;
9878 for (i = 0; i < num; ++i)
9879 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9881 if (tb->interfaces) {
9882 klass->interface_count = mono_array_length (tb->interfaces);
9883 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9884 for (i = 0; i < klass->interface_count; ++i) {
9885 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9886 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9887 ensure_runtime_vtable (klass->interfaces [i]);
9890 } else if (klass->generic_class){
9891 ensure_generic_class_runtime_vtable (klass);
9894 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9895 for (i = 0; i < klass->method.count; ++i)
9896 klass->methods [i]->slot = i;
9898 mono_class_setup_interface_offsets (klass);
9899 mono_class_setup_interface_id (klass);
9903 * The generic vtable is needed even if image->run is not set since some
9904 * runtime code like ves_icall_Type_GetMethodsByName depends on
9905 * method->slot being defined.
9909 * tb->methods could not be freed since it is used for determining
9910 * overrides during dynamic vtable construction.
9915 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9917 MonoReflectionTypeBuilder *tb;
9923 g_assert (klass->image->dynamic);
9925 if (!klass->reflection_info)
9928 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9930 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9934 for (i = 0; i < tb->num_methods; ++i) {
9935 MonoReflectionMethodBuilder *mb =
9936 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9937 if (mb->override_method)
9943 *overrides = g_new0 (MonoMethod*, onum * 2);
9946 for (i = 0; i < tb->num_methods; ++i) {
9947 MonoReflectionMethodBuilder *mb =
9948 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9949 if (mb->override_method) {
9950 (*overrides) [onum * 2] =
9951 mb->override_method->method;
9952 (*overrides) [onum * 2 + 1] =
9955 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9956 g_assert (mb->override_method->method);
9957 g_assert (mb->mhandle);
9964 *num_overrides = onum;
9968 typebuilder_setup_fields (MonoClass *klass)
9970 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9971 MonoReflectionFieldBuilder *fb;
9972 MonoClassField *field;
9973 MonoMemPool *mp = klass->image->mempool;
9976 guint32 len, idx, real_size = 0;
9978 klass->field.count = tb->num_fields;
9979 klass->field.first = 0;
9981 if (tb->class_size) {
9982 g_assert ((tb->packing_size & 0xfffffff0) == 0);
9983 klass->packing_size = tb->packing_size;
9984 real_size = klass->instance_size + tb->class_size;
9987 if (!klass->field.count) {
9988 klass->instance_size = MAX (klass->instance_size, real_size);
9992 klass->fields = mp_g_new0 (mp, MonoClassField, klass->field.count);
9993 klass->field_def_values = mp_g_new0 (mp, MonoFieldDefaultValue, klass->field.count);
9995 for (i = 0; i < klass->field.count; ++i) {
9996 fb = mono_array_get (tb->fields, gpointer, i);
9997 field = &klass->fields [i];
9998 field->name = mp_string_to_utf8 (mp, fb->name);
10000 field->type = mono_metadata_type_dup (mp, fb->type->type);
10001 field->type->attrs = fb->attrs;
10003 field->type = fb->type->type;
10005 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10006 klass->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10007 if (fb->offset != -1)
10008 field->offset = fb->offset;
10009 field->parent = klass;
10010 fb->handle = field;
10011 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10013 if (fb->def_value) {
10014 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10015 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10016 idx = encode_constant (assembly, fb->def_value, &klass->field_def_values [i].def_type);
10017 /* Copy the data from the blob since it might get realloc-ed */
10018 p = assembly->blob.data + idx;
10019 len = mono_metadata_decode_blob_size (p, &p2);
10021 klass->field_def_values [i].data = mono_mempool_alloc (mp, len);
10022 memcpy ((gpointer)klass->field_def_values [i].data, p, len);
10026 klass->instance_size = MAX (klass->instance_size, real_size);
10027 mono_class_layout_fields (klass);
10031 typebuilder_setup_properties (MonoClass *klass)
10033 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10034 MonoReflectionPropertyBuilder *pb;
10035 MonoMemPool *mp = klass->image->mempool;
10038 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10039 klass->property.first = 0;
10041 klass->properties = mp_g_new0 (mp, MonoProperty, klass->property.count);
10042 for (i = 0; i < klass->property.count; ++i) {
10043 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10044 klass->properties [i].parent = klass;
10045 klass->properties [i].attrs = pb->attrs;
10046 klass->properties [i].name = mp_string_to_utf8 (mp, pb->name);
10047 if (pb->get_method)
10048 klass->properties [i].get = pb->get_method->mhandle;
10049 if (pb->set_method)
10050 klass->properties [i].set = pb->set_method->mhandle;
10052 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
10056 MonoReflectionEvent *
10057 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10059 MonoEvent *event = g_new0 (MonoEvent, 1);
10063 klass = my_mono_class_from_mono_type (tb->type.type);
10065 event->parent = klass;
10066 event->attrs = eb->attrs;
10067 event->name = mono_string_to_utf8 (eb->name);
10068 if (eb->add_method)
10069 event->add = eb->add_method->mhandle;
10070 if (eb->remove_method)
10071 event->remove = eb->remove_method->mhandle;
10072 if (eb->raise_method)
10073 event->raise = eb->raise_method->mhandle;
10075 if (eb->other_methods) {
10076 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10077 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10078 MonoReflectionMethodBuilder *mb =
10079 mono_array_get (eb->other_methods,
10080 MonoReflectionMethodBuilder*, j);
10081 event->other [j] = mb->mhandle;
10085 return mono_event_get_object (mono_object_domain (tb), klass, event);
10089 typebuilder_setup_events (MonoClass *klass)
10091 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10092 MonoReflectionEventBuilder *eb;
10093 MonoMemPool *mp = klass->image->mempool;
10096 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
10097 klass->event.first = 0;
10099 klass->events = mp_g_new0 (mp, MonoEvent, klass->event.count);
10100 for (i = 0; i < klass->event.count; ++i) {
10101 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10102 klass->events [i].parent = klass;
10103 klass->events [i].attrs = eb->attrs;
10104 klass->events [i].name = mp_string_to_utf8 (mp, eb->name);
10105 if (eb->add_method)
10106 klass->events [i].add = eb->add_method->mhandle;
10107 if (eb->remove_method)
10108 klass->events [i].remove = eb->remove_method->mhandle;
10109 if (eb->raise_method)
10110 klass->events [i].raise = eb->raise_method->mhandle;
10112 if (eb->other_methods) {
10113 klass->events [i].other = mp_g_new0 (mp, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10114 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10115 MonoReflectionMethodBuilder *mb =
10116 mono_array_get (eb->other_methods,
10117 MonoReflectionMethodBuilder*, j);
10118 klass->events [i].other [j] = mb->mhandle;
10121 mono_save_custom_attrs (klass->image, &klass->events [i], eb->cattrs);
10126 remove_instantiations_of (gpointer key,
10128 gpointer user_data)
10130 MonoType *type = (MonoType*)key;
10131 MonoClass *klass = (MonoClass*)user_data;
10133 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10139 MonoReflectionType*
10140 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10143 MonoDomain* domain;
10144 MonoReflectionType* res;
10147 MONO_ARCH_SAVE_REGS;
10149 domain = mono_object_domain (tb);
10150 klass = my_mono_class_from_mono_type (tb->type.type);
10152 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10155 * we need to lock the domain because the lock will be taken inside
10156 * So, we need to keep the locking order correct.
10158 mono_domain_lock (domain);
10159 mono_loader_lock ();
10160 if (klass->wastypebuilder) {
10161 mono_loader_unlock ();
10162 mono_domain_unlock (domain);
10163 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10166 * Fields to set in klass:
10167 * the various flags: delegate/unicode/contextbound etc.
10169 klass->flags = tb->attrs;
10170 klass->has_cctor = 1;
10171 klass->has_finalize = 1;
10174 if (!((MonoDynamicImage*)klass->image)->run) {
10175 if (klass->generic_container) {
10176 /* FIXME: The code below can't handle generic classes */
10177 klass->wastypebuilder = TRUE;
10178 mono_loader_unlock ();
10179 mono_domain_unlock (domain);
10180 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10185 /* enums are done right away */
10186 if (!klass->enumtype)
10187 ensure_runtime_vtable (klass);
10189 if (tb->subtypes) {
10190 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10191 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10192 klass->nested_classes = g_list_prepend_mempool (klass->image->mempool, klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
10196 klass->nested_classes_inited = TRUE;
10198 /* fields and object layout */
10199 if (klass->parent) {
10200 if (!klass->parent->size_inited)
10201 mono_class_init (klass->parent);
10202 klass->instance_size = klass->parent->instance_size;
10203 klass->sizes.class_size = 0;
10204 klass->min_align = klass->parent->min_align;
10205 /* if the type has no fields we won't call the field_setup
10206 * routine which sets up klass->has_references.
10208 klass->has_references |= klass->parent->has_references;
10210 klass->instance_size = sizeof (MonoObject);
10211 klass->min_align = 1;
10214 /* FIXME: handle packing_size and instance_size */
10215 typebuilder_setup_fields (klass);
10217 typebuilder_setup_properties (klass);
10219 typebuilder_setup_events (klass);
10221 klass->wastypebuilder = TRUE;
10224 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10225 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10226 * we want to return normal System.MonoType objects, so clear these out from the cache.
10228 if (domain->type_hash && klass->generic_container)
10229 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10231 mono_loader_unlock ();
10232 mono_domain_unlock (domain);
10234 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10235 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10236 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10239 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10240 g_assert (res != (MonoReflectionType*)tb);
10246 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10248 MonoGenericParam *param;
10251 MONO_ARCH_SAVE_REGS;
10253 param = g_new0 (MonoGenericParam, 1);
10255 if (gparam->mbuilder) {
10256 if (!gparam->mbuilder->generic_container) {
10257 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10258 MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
10259 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10260 gparam->mbuilder->generic_container->is_method = TRUE;
10262 param->owner = gparam->mbuilder->generic_container;
10263 } else if (gparam->tbuilder) {
10264 if (!gparam->tbuilder->generic_container) {
10265 MonoClass *klass = my_mono_class_from_mono_type (gparam->tbuilder->type.type);
10266 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10267 gparam->tbuilder->generic_container->owner.klass = klass;
10269 param->owner = gparam->tbuilder->generic_container;
10272 param->name = mono_string_to_utf8 (gparam->name);
10273 param->num = gparam->index;
10275 image = &gparam->tbuilder->module->dynamic_image->image;
10276 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10278 gparam->type.type = ¶m->pklass->byval_arg;
10280 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
10281 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10285 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10287 MonoDynamicImage *assembly = sig->module->dynamic_image;
10288 guint32 na = mono_array_length (sig->arguments);
10293 sigbuffer_init (&buf, 32);
10295 sigbuffer_add_value (&buf, 0x07);
10296 sigbuffer_add_value (&buf, na);
10297 for (i = 0; i < na; ++i) {
10298 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10299 encode_reflection_type (assembly, type, &buf);
10302 buflen = buf.p - buf.buf;
10303 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10304 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10305 sigbuffer_free (&buf);
10311 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10313 MonoDynamicImage *assembly = sig->module->dynamic_image;
10314 guint32 na = mono_array_length (sig->arguments);
10319 sigbuffer_init (&buf, 32);
10321 sigbuffer_add_value (&buf, 0x06);
10322 for (i = 0; i < na; ++i) {
10323 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10324 encode_reflection_type (assembly, type, &buf);
10327 buflen = buf.p - buf.buf;
10328 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10329 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10330 sigbuffer_free (&buf);
10336 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10338 ReflectionMethodBuilder rmb;
10339 MonoMethodSignature *sig;
10344 sig = dynamic_method_to_signature (mb);
10346 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10349 * Resolve references.
10352 * Every second entry in the refs array is reserved for storing handle_class,
10353 * which is needed by the ldtoken implementation in the JIT.
10355 rmb.nrefs = mb->nrefs;
10356 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10357 for (i = 0; i < mb->nrefs; i += 2) {
10358 MonoClass *handle_class;
10360 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10362 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10363 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10365 * The referenced DynamicMethod should already be created by the managed
10366 * code, except in the case of circular references. In that case, we store
10367 * method in the refs array, and fix it up later when the referenced
10368 * DynamicMethod is created.
10370 if (method->mhandle) {
10371 ref = method->mhandle;
10373 /* FIXME: GC object stored in unmanaged memory */
10376 /* FIXME: GC object stored in unmanaged memory */
10377 method->referenced_by = g_slist_append (method->referenced_by, mb);
10379 handle_class = mono_defaults.methodhandle_class;
10381 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10384 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10389 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10390 rmb.refs [i + 1] = handle_class;
10393 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10395 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10397 /* Fix up refs entries pointing at us */
10398 for (l = mb->referenced_by; l; l = l->next) {
10399 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10400 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10403 g_assert (method->mhandle);
10405 data = (gpointer*)wrapper->method_data;
10406 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10407 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10408 data [i + 1] = mb->mhandle;
10411 g_slist_free (mb->referenced_by);
10415 /* ilgen is no longer needed */
10419 #endif /* DISABLE_REFLECTION_EMIT */
10422 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10427 mono_runtime_free_method (
10428 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10433 * mono_reflection_is_valid_dynamic_token:
10435 * Returns TRUE if token is valid.
10439 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10441 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10444 #ifndef DISABLE_REFLECTION_EMIT
10447 * mono_reflection_lookup_dynamic_token:
10449 * Finish the Builder object pointed to by TOKEN and return the corresponding
10450 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10451 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10455 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10457 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10461 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10464 g_assert_not_reached ();
10470 handle_class = &klass;
10471 return resolve_object (image, obj, handle_class, context);
10475 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10477 gpointer result = NULL;
10479 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10480 result = mono_string_intern ((MonoString*)obj);
10481 *handle_class = NULL;
10483 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10484 MonoReflectionType *tb = (MonoReflectionType*)obj;
10486 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10487 result = mono_class_from_mono_type (inflated);
10488 mono_metadata_free_type (inflated);
10490 result = mono_class_from_mono_type (tb->type);
10492 *handle_class = mono_defaults.typehandle_class;
10494 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10495 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10496 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10497 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10498 result = ((MonoReflectionMethod*)obj)->method;
10500 result = mono_class_inflate_generic_method (result, context);
10501 *handle_class = mono_defaults.methodhandle_class;
10503 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10504 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10505 result = mb->mhandle;
10507 /* Type is not yet created */
10508 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10510 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10513 * Hopefully this has been filled in by calling CreateType() on the
10517 * TODO: This won't work if the application finishes another
10518 * TypeBuilder instance instead of this one.
10520 result = mb->mhandle;
10523 result = mono_class_inflate_generic_method (result, context);
10524 *handle_class = mono_defaults.methodhandle_class;
10525 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10526 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10528 result = cb->mhandle;
10530 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10532 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10533 result = cb->mhandle;
10536 result = mono_class_inflate_generic_method (result, context);
10537 *handle_class = mono_defaults.methodhandle_class;
10538 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10539 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10541 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
10542 MonoClass *class = mono_class_from_mono_type (inflated);
10543 MonoClassField *inflated_field;
10544 gpointer iter = NULL;
10545 mono_metadata_free_type (inflated);
10546 while ((inflated_field = mono_class_get_fields (class, &iter))) {
10547 if (!strcmp (field->name, inflated_field->name))
10550 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
10551 result = inflated_field;
10555 *handle_class = mono_defaults.fieldhandle_class;
10557 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10558 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10559 result = fb->handle;
10562 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10564 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10565 result = fb->handle;
10568 if (fb->handle && fb->handle->parent->generic_container) {
10569 MonoClass *klass = fb->handle->parent;
10570 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10571 MonoClass *inflated = mono_class_from_mono_type (type);
10573 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
10575 mono_metadata_free_type (type);
10577 *handle_class = mono_defaults.fieldhandle_class;
10578 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10579 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10582 klass = tb->type.type->data.klass;
10583 if (klass->wastypebuilder) {
10584 /* Already created */
10588 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10589 result = tb->type.type->data.klass;
10592 *handle_class = mono_defaults.typehandle_class;
10593 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10594 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10595 MonoMethodSignature *sig;
10598 if (helper->arguments)
10599 nargs = mono_array_length (helper->arguments);
10603 sig = mono_metadata_signature_alloc (image, nargs);
10604 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10605 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10607 if (helper->call_conv == 0) /* unmanaged */
10608 sig->call_convention = helper->unmanaged_call_conv - 1;
10610 if (helper->call_conv & 0x02)
10611 sig->call_convention = MONO_CALL_VARARG;
10613 sig->call_convention = MONO_CALL_DEFAULT;
10615 sig->param_count = nargs;
10616 /* TODO: Copy type ? */
10617 sig->ret = helper->return_type->type;
10618 for (i = 0; i < nargs; ++i) {
10619 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10620 sig->params [i] = rt->type;
10624 *handle_class = NULL;
10625 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10626 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10627 /* Already created by the managed code */
10628 g_assert (method->mhandle);
10629 result = method->mhandle;
10630 *handle_class = mono_defaults.methodhandle_class;
10631 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10632 MonoReflectionType *tb = (MonoReflectionType*)obj;
10633 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10634 result = mono_class_from_mono_type (type);
10635 *handle_class = mono_defaults.typehandle_class;
10637 mono_metadata_free_type (type);
10638 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10639 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10640 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10641 result = mono_class_from_mono_type (type);
10642 *handle_class = mono_defaults.typehandle_class;
10644 mono_metadata_free_type (type);
10645 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10646 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10647 MonoClass *inflated;
10650 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10651 inflated = mono_class_from_mono_type (type);
10653 g_assert (f->fb->handle);
10654 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
10656 mono_metadata_free_type (type);
10657 *handle_class = mono_defaults.fieldhandle_class;
10658 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10659 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10660 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10661 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10662 g_assert (c->cb->mhandle);
10663 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10664 *handle_class = mono_defaults.methodhandle_class;
10665 mono_metadata_free_type (type);
10666 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10667 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10668 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10669 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10670 g_assert (m->mb->mhandle);
10671 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10672 *handle_class = mono_defaults.methodhandle_class;
10673 mono_metadata_free_type (type);
10675 g_print (obj->vtable->klass->name);
10676 g_assert_not_reached ();
10681 #else /* DISABLE_REFLECTION_EMIT */
10684 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10686 g_assert_not_reached ();
10691 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10693 g_assert_not_reached ();
10697 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10699 g_assert_not_reached ();
10703 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10705 g_assert_not_reached ();
10709 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10711 g_assert_not_reached ();
10715 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
10717 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10721 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
10723 g_assert_not_reached ();
10726 MonoReflectionModule *
10727 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
10729 g_assert_not_reached ();
10734 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
10736 g_assert_not_reached ();
10741 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
10743 g_assert_not_reached ();
10748 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
10749 gboolean create_methodspec, gboolean register_token)
10751 g_assert_not_reached ();
10756 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
10761 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10762 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10765 g_assert_not_reached ();
10769 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10772 *num_overrides = 0;
10775 MonoReflectionEvent *
10776 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10778 g_assert_not_reached ();
10782 MonoReflectionType*
10783 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10785 g_assert_not_reached ();
10790 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10792 g_assert_not_reached ();
10796 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10798 g_assert_not_reached ();
10803 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10805 g_assert_not_reached ();
10810 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10815 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10820 #endif /* DISABLE_REFLECTION_EMIT */
10822 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10823 const static guint32 declsec_flags_map[] = {
10824 0x00000000, /* empty */
10825 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10826 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10827 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10828 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10829 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10830 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10831 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10832 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10833 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10834 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10835 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10836 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10837 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10838 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10839 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10840 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10841 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10842 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10846 * Returns flags that includes all available security action associated to the handle.
10847 * @token: metadata token (either for a class or a method)
10848 * @image: image where resides the metadata.
10851 mono_declsec_get_flags (MonoImage *image, guint32 token)
10853 int index = mono_metadata_declsec_from_index (image, token);
10854 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10855 guint32 result = 0;
10859 /* HasSecurity can be present for other, not specially encoded, attributes,
10860 e.g. SuppressUnmanagedCodeSecurityAttribute */
10864 for (i = index; i < t->rows; i++) {
10865 guint32 cols [MONO_DECL_SECURITY_SIZE];
10867 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10868 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10871 action = cols [MONO_DECL_SECURITY_ACTION];
10872 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10873 result |= declsec_flags_map [action];
10875 g_assert_not_reached ();
10882 * Get the security actions (in the form of flags) associated with the specified method.
10884 * @method: The method for which we want the declarative security flags.
10885 * Return the declarative security flags for the method (only).
10887 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10888 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10891 mono_declsec_flags_from_method (MonoMethod *method)
10893 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10894 /* FIXME: No cache (for the moment) */
10895 guint32 idx = mono_method_get_index (method);
10896 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10897 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10898 return mono_declsec_get_flags (method->klass->image, idx);
10904 * Get the security actions (in the form of flags) associated with the specified class.
10906 * @klass: The class for which we want the declarative security flags.
10907 * Return the declarative security flags for the class.
10909 * Note: We cache the flags inside the MonoClass structure as this will get
10910 * called very often (at least for each method).
10913 mono_declsec_flags_from_class (MonoClass *klass)
10915 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10916 if (!klass->declsec_flags) {
10917 guint32 idx = mono_metadata_token_index (klass->type_token);
10918 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10919 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10920 /* we cache the flags on classes */
10921 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10923 return klass->declsec_flags;
10929 * Get the security actions (in the form of flags) associated with the specified assembly.
10931 * @assembly: The assembly for which we want the declarative security flags.
10932 * Return the declarative security flags for the assembly.
10935 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10937 guint32 idx = 1; /* there is only one assembly */
10938 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10939 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10940 return mono_declsec_get_flags (assembly->image, idx);
10945 * Fill actions for the specific index (which may either be an encoded class token or
10946 * an encoded method token) from the metadata image.
10947 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10950 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10951 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10953 MonoBoolean result = FALSE;
10955 guint32 cols [MONO_DECL_SECURITY_SIZE];
10956 int index = mono_metadata_declsec_from_index (image, token);
10959 t = &image->tables [MONO_TABLE_DECLSECURITY];
10960 for (i = index; i < t->rows; i++) {
10961 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10963 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10966 /* if present only replace (class) permissions with method permissions */
10967 /* if empty accept either class or method permissions */
10968 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10969 if (!actions->demand.blob) {
10970 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10971 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10972 actions->demand.blob = (char*) (blob + 2);
10973 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10976 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10977 if (!actions->noncasdemand.blob) {
10978 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10979 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10980 actions->noncasdemand.blob = (char*) (blob + 2);
10981 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10984 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10985 if (!actions->demandchoice.blob) {
10986 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10987 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10988 actions->demandchoice.blob = (char*) (blob + 2);
10989 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10999 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
11000 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11002 guint32 idx = mono_metadata_token_index (klass->type_token);
11003 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11004 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11005 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11009 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11010 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11012 guint32 idx = mono_method_get_index (method);
11013 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11014 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11015 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11019 * Collect all actions (that requires to generate code in mini) assigned for
11020 * the specified method.
11021 * Note: Don't use the content of actions if the function return FALSE.
11024 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11026 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11027 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11028 MonoBoolean result = FALSE;
11031 /* quick exit if no declarative security is present in the metadata */
11032 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11035 /* we want the original as the wrapper is "free" of the security informations */
11036 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11037 method = mono_marshal_method_from_wrapper (method);
11042 /* First we look for method-level attributes */
11043 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11044 mono_class_init (method->klass);
11045 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11047 result = mono_declsec_get_method_demands_params (method, demands,
11048 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11051 /* Here we use (or create) the class declarative cache to look for demands */
11052 flags = mono_declsec_flags_from_class (method->klass);
11053 if (flags & mask) {
11055 mono_class_init (method->klass);
11056 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11058 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11059 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11062 /* The boolean return value is used as a shortcut in case nothing needs to
11063 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11069 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11071 * Note: Don't use the content of actions if the function return FALSE.
11074 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11076 MonoBoolean result = FALSE;
11079 /* quick exit if no declarative security is present in the metadata */
11080 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11083 /* we want the original as the wrapper is "free" of the security informations */
11084 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11085 method = mono_marshal_method_from_wrapper (method);
11090 /* results are independant - zeroize both */
11091 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11092 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11094 /* First we look for method-level attributes */
11095 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11096 mono_class_init (method->klass);
11098 result = mono_declsec_get_method_demands_params (method, cmethod,
11099 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11102 /* Here we use (or create) the class declarative cache to look for demands */
11103 flags = mono_declsec_flags_from_class (method->klass);
11104 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11105 mono_class_init (method->klass);
11107 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11108 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11115 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11117 * @klass The inherited class - this is the class that provides the security check (attributes)
11119 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11121 * Note: Don't use the content of actions if the function return FALSE.
11124 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11126 MonoBoolean result = FALSE;
11129 /* quick exit if no declarative security is present in the metadata */
11130 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11133 /* Here we use (or create) the class declarative cache to look for demands */
11134 flags = mono_declsec_flags_from_class (klass);
11135 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11136 mono_class_init (klass);
11137 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11139 result |= mono_declsec_get_class_demands_params (klass, demands,
11140 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11147 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11149 * Note: Don't use the content of actions if the function return FALSE.
11152 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11154 /* quick exit if no declarative security is present in the metadata */
11155 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11158 /* we want the original as the wrapper is "free" of the security informations */
11159 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11160 method = mono_marshal_method_from_wrapper (method);
11165 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11166 mono_class_init (method->klass);
11167 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11169 return mono_declsec_get_method_demands_params (method, demands,
11170 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11177 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11179 guint32 cols [MONO_DECL_SECURITY_SIZE];
11183 int index = mono_metadata_declsec_from_index (image, token);
11187 t = &image->tables [MONO_TABLE_DECLSECURITY];
11188 for (i = index; i < t->rows; i++) {
11189 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11191 /* shortcut - index are ordered */
11192 if (token != cols [MONO_DECL_SECURITY_PARENT])
11195 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11196 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11197 entry->blob = (char*) (metadata + 2);
11198 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11207 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11209 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11210 guint32 idx = mono_method_get_index (method);
11211 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11212 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11213 return get_declsec_action (method->klass->image, idx, action, entry);
11219 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11222 guint32 flags = mono_declsec_flags_from_class (klass);
11223 if (declsec_flags_map [action] & flags) {
11224 guint32 idx = mono_metadata_token_index (klass->type_token);
11225 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11226 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11227 return get_declsec_action (klass->image, idx, action, entry);
11233 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11235 guint32 idx = 1; /* there is only one assembly */
11236 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11237 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11239 return get_declsec_action (assembly->image, idx, action, entry);
11243 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11245 MonoObject *res, *exc;
11247 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11248 static MonoMethod *method = NULL;
11250 if (!System_Reflection_Emit_TypeBuilder) {
11251 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11252 g_assert (System_Reflection_Emit_TypeBuilder);
11254 if (method == NULL) {
11255 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11260 * The result of mono_type_get_object () might be a System.MonoType but we
11261 * need a TypeBuilder so use klass->reflection_info.
11263 g_assert (klass->reflection_info);
11264 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11266 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11268 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11272 return *(MonoBoolean*)mono_object_unbox (res);