2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
41 static void* reflection_info_desc = NULL;
42 #define MOVING_GC_REGISTER(addr) do { \
43 if (!reflection_info_desc) { \
45 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
47 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
50 #define MOVING_GC_REGISTER(addr)
59 #define TEXT_OFFSET 512
60 #define CLI_H_SIZE 136
61 #define FILE_ALIGN 512
62 #define VIRT_ALIGN 8192
63 #define START_TEXT_RVA 0x00002000
66 MonoReflectionILGen *ilgen;
67 MonoReflectionType *rtype;
68 MonoArray *parameters;
69 MonoArray *generic_params;
70 MonoGenericContainer *generic_container;
76 guint32 *table_idx; /* note: it's a pointer */
80 MonoBoolean init_locals;
81 MonoBoolean skip_visibility;
82 MonoArray *return_modreq;
83 MonoArray *return_modopt;
84 MonoArray *param_modreq;
85 MonoArray *param_modopt;
86 MonoArray *permissions;
91 int charset, extra_flags, native_cc;
92 MonoString *dll, *dllentry;
93 } ReflectionMethodBuilder;
97 MonoReflectionGenericParam *gparam;
98 } GenericParamTableEntry;
100 const unsigned char table_sizes [MONO_TABLE_NUM] = {
110 MONO_INTERFACEIMPL_SIZE,
111 MONO_MEMBERREF_SIZE, /* 0x0A */
113 MONO_CUSTOM_ATTR_SIZE,
114 MONO_FIELD_MARSHAL_SIZE,
115 MONO_DECL_SECURITY_SIZE,
116 MONO_CLASS_LAYOUT_SIZE,
117 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
118 MONO_STAND_ALONE_SIGNATURE_SIZE,
122 MONO_PROPERTY_MAP_SIZE,
125 MONO_METHOD_SEMA_SIZE,
126 MONO_METHODIMPL_SIZE,
127 MONO_MODULEREF_SIZE, /* 0x1A */
133 MONO_ASSEMBLY_SIZE, /* 0x20 */
134 MONO_ASSEMBLY_PROCESSOR_SIZE,
135 MONO_ASSEMBLYOS_SIZE,
136 MONO_ASSEMBLYREF_SIZE,
137 MONO_ASSEMBLYREFPROC_SIZE,
138 MONO_ASSEMBLYREFOS_SIZE,
142 MONO_NESTED_CLASS_SIZE,
144 MONO_GENERICPARAM_SIZE, /* 0x2A */
145 MONO_METHODSPEC_SIZE,
146 MONO_GENPARCONSTRAINT_SIZE
150 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
151 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
152 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
153 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
154 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
155 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
156 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
157 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
158 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
159 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
160 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
161 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
162 static void ensure_runtime_vtable (MonoClass *klass);
163 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
164 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
165 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
166 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
167 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
168 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
169 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
170 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
173 mono_reflection_init (void)
178 sigbuffer_init (SigBuffer *buf, int size)
180 buf->buf = g_malloc (size);
182 buf->end = buf->buf + size;
186 sigbuffer_make_room (SigBuffer *buf, int size)
188 if (buf->end - buf->p < size) {
189 int new_size = buf->end - buf->buf + size + 32;
190 char *p = g_realloc (buf->buf, new_size);
191 size = buf->p - buf->buf;
194 buf->end = buf->buf + new_size;
199 sigbuffer_add_value (SigBuffer *buf, guint32 val)
201 sigbuffer_make_room (buf, 6);
202 mono_metadata_encode_value (val, buf->p, &buf->p);
206 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
208 sigbuffer_make_room (buf, 1);
214 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
216 sigbuffer_make_room (buf, size);
217 memcpy (buf->p, p, size);
222 sigbuffer_free (SigBuffer *buf)
230 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
234 image_g_malloc (MonoImage *image, guint size)
237 return mono_image_alloc (image, size);
239 return g_malloc (size);
245 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
249 image_g_malloc0 (MonoImage *image, guint size)
252 return mono_image_alloc0 (image, size);
254 return g_malloc0 (size);
258 image_strdup (MonoImage *image, const char *s)
261 return mono_image_strdup (image, s);
266 #define image_g_new(image,struct_type, n_structs) \
267 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
269 #define image_g_new0(image,struct_type, n_structs) \
270 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
274 alloc_table (MonoDynamicTable *table, guint nrows)
277 g_assert (table->columns);
278 if (nrows + 1 >= table->alloc_rows) {
279 while (nrows + 1 >= table->alloc_rows) {
280 if (table->alloc_rows == 0)
281 table->alloc_rows = 16;
283 table->alloc_rows *= 2;
286 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
291 make_room_in_stream (MonoDynamicStream *stream, int size)
293 if (size <= stream->alloc_size)
296 while (stream->alloc_size <= size) {
297 if (stream->alloc_size < 4096)
298 stream->alloc_size = 4096;
300 stream->alloc_size *= 2;
303 stream->data = g_realloc (stream->data, stream->alloc_size);
307 string_heap_insert (MonoDynamicStream *sh, const char *str)
311 gpointer oldkey, oldval;
313 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
314 return GPOINTER_TO_UINT (oldval);
316 len = strlen (str) + 1;
319 make_room_in_stream (sh, idx + len);
322 * We strdup the string even if we already copy them in sh->data
323 * so that the string pointers in the hash remain valid even if
324 * we need to realloc sh->data. We may want to avoid that later.
326 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
327 memcpy (sh->data + idx, str, len);
333 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
335 char *name = mono_string_to_utf8 (str);
337 idx = string_heap_insert (sh, name);
343 string_heap_init (MonoDynamicStream *sh)
346 sh->alloc_size = 4096;
347 sh->data = g_malloc (4096);
348 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
349 string_heap_insert (sh, "");
353 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
357 make_room_in_stream (stream, stream->index + len);
358 memcpy (stream->data + stream->index, data, len);
360 stream->index += len;
362 * align index? Not without adding an additional param that controls it since
363 * we may store a blob value in pieces.
369 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
373 make_room_in_stream (stream, stream->index + len);
374 memset (stream->data + stream->index, 0, len);
376 stream->index += len;
381 stream_data_align (MonoDynamicStream *stream)
384 guint32 count = stream->index % 4;
386 /* we assume the stream data will be aligned */
388 mono_image_add_stream_data (stream, buf, 4 - count);
392 mono_blob_entry_hash (const char* str)
396 len = mono_metadata_decode_blob_size (str, &str);
400 for (str += 1; str < end; str++)
401 h = (h << 5) - h + *str;
409 mono_blob_entry_equal (const char *str1, const char *str2) {
413 len = mono_metadata_decode_blob_size (str1, &end1);
414 len2 = mono_metadata_decode_blob_size (str2, &end2);
417 return memcmp (end1, end2, len) == 0;
421 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
425 gpointer oldkey, oldval;
427 copy = g_malloc (s1+s2);
428 memcpy (copy, b1, s1);
429 memcpy (copy + s1, b2, s2);
430 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
432 idx = GPOINTER_TO_UINT (oldval);
434 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
435 mono_image_add_stream_data (&assembly->blob, b2, s2);
436 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
442 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
446 guint32 size = buf->p - buf->buf;
448 g_assert (size <= (buf->end - buf->buf));
449 mono_metadata_encode_value (size, b, &b);
450 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
454 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
455 * dest may be misaligned.
458 swap_with_size (char *dest, const char* val, int len, int nelem) {
459 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
462 for (elem = 0; elem < nelem; ++elem) {
488 g_assert_not_reached ();
494 memcpy (dest, val, len * nelem);
499 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
503 guint32 idx = 0, len;
505 len = str->length * 2;
506 mono_metadata_encode_value (len, b, &b);
507 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
509 char *swapped = g_malloc (2 * mono_string_length (str));
510 const char *p = (const char*)mono_string_chars (str);
512 swap_with_size (swapped, p, 2, mono_string_length (str));
513 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
517 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
522 /* modified version needed to handle building corlib */
524 my_mono_class_from_mono_type (MonoType *type) {
525 switch (type->type) {
526 case MONO_TYPE_ARRAY:
528 case MONO_TYPE_SZARRAY:
529 case MONO_TYPE_GENERICINST:
530 return mono_class_from_mono_type (type);
533 g_assert (type->data.generic_param->pklass);
534 return type->data.generic_param->pklass;
536 /* should be always valid when we reach this case... */
537 return type->data.klass;
542 default_class_from_mono_type (MonoType *type)
544 switch (type->type) {
545 case MONO_TYPE_OBJECT:
546 return mono_defaults.object_class;
548 return mono_defaults.void_class;
549 case MONO_TYPE_BOOLEAN:
550 return mono_defaults.boolean_class;
552 return mono_defaults.char_class;
554 return mono_defaults.sbyte_class;
556 return mono_defaults.byte_class;
558 return mono_defaults.int16_class;
560 return mono_defaults.uint16_class;
562 return mono_defaults.int32_class;
564 return mono_defaults.uint32_class;
566 return mono_defaults.int_class;
568 return mono_defaults.uint_class;
570 return mono_defaults.int64_class;
572 return mono_defaults.uint64_class;
574 return mono_defaults.single_class;
576 return mono_defaults.double_class;
577 case MONO_TYPE_STRING:
578 return mono_defaults.string_class;
580 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
581 g_assert_not_reached ();
588 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
591 MonoGenericInst *class_inst;
596 class_inst = gclass->context.class_inst;
598 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
599 klass = gclass->container_class;
600 sigbuffer_add_value (buf, klass->byval_arg.type);
601 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
603 sigbuffer_add_value (buf, class_inst->type_argc);
604 for (i = 0; i < class_inst->type_argc; ++i)
605 encode_type (assembly, class_inst->type_argv [i], buf);
610 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
613 g_assert_not_reached ();
618 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
622 case MONO_TYPE_BOOLEAN:
636 case MONO_TYPE_STRING:
637 case MONO_TYPE_OBJECT:
638 case MONO_TYPE_TYPEDBYREF:
639 sigbuffer_add_value (buf, type->type);
642 sigbuffer_add_value (buf, type->type);
643 encode_type (assembly, type->data.type, buf);
645 case MONO_TYPE_SZARRAY:
646 sigbuffer_add_value (buf, type->type);
647 encode_type (assembly, &type->data.klass->byval_arg, buf);
649 case MONO_TYPE_VALUETYPE:
650 case MONO_TYPE_CLASS: {
651 MonoClass *k = mono_class_from_mono_type (type);
653 if (k->generic_container) {
654 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
655 encode_generic_class (assembly, gclass, buf);
658 * Make sure we use the correct type.
660 sigbuffer_add_value (buf, k->byval_arg.type);
662 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
663 * otherwise two typerefs could point to the same type, leading to
664 * verification errors.
666 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
670 case MONO_TYPE_ARRAY:
671 sigbuffer_add_value (buf, type->type);
672 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
673 sigbuffer_add_value (buf, type->data.array->rank);
674 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
675 sigbuffer_add_value (buf, 0);
677 case MONO_TYPE_GENERICINST:
678 encode_generic_class (assembly, type->data.generic_class, buf);
682 sigbuffer_add_value (buf, type->type);
683 sigbuffer_add_value (buf, type->data.generic_param->num);
686 g_error ("need to encode type %x", type->type);
691 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
694 sigbuffer_add_value (buf, MONO_TYPE_VOID);
699 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
700 encode_type (assembly, type->type, buf);
704 g_assert_not_reached ();
709 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
714 for (i = 0; i < mono_array_length (modreq); ++i) {
715 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
716 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
717 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
721 for (i = 0; i < mono_array_length (modopt); ++i) {
722 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
723 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
724 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
730 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
734 guint32 nparams = sig->param_count;
740 sigbuffer_init (&buf, 32);
742 * FIXME: vararg, explicit_this, differenc call_conv values...
744 idx = sig->call_convention;
746 idx |= 0x20; /* hasthis */
747 if (sig->generic_param_count)
748 idx |= 0x10; /* generic */
749 sigbuffer_add_byte (&buf, idx);
750 if (sig->generic_param_count)
751 sigbuffer_add_value (&buf, sig->generic_param_count);
752 sigbuffer_add_value (&buf, nparams);
753 encode_type (assembly, sig->ret, &buf);
754 for (i = 0; i < nparams; ++i) {
755 if (i == sig->sentinelpos)
756 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
757 encode_type (assembly, sig->params [i], &buf);
759 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
760 sigbuffer_free (&buf);
765 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
768 * FIXME: reuse code from method_encode_signature().
772 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
773 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
774 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
777 sigbuffer_init (&buf, 32);
778 /* LAMESPEC: all the call conv spec is foobared */
779 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
780 if (mb->call_conv & 2)
781 idx |= 0x5; /* vararg */
782 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
783 idx |= 0x20; /* hasthis */
785 idx |= 0x10; /* generic */
786 sigbuffer_add_byte (&buf, idx);
788 sigbuffer_add_value (&buf, ngparams);
789 sigbuffer_add_value (&buf, nparams + notypes);
790 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
791 encode_reflection_type (assembly, mb->rtype, &buf);
792 for (i = 0; i < nparams; ++i) {
793 MonoArray *modreq = NULL;
794 MonoArray *modopt = NULL;
795 MonoReflectionType *pt;
797 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
798 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
799 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
800 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
801 encode_custom_modifiers (assembly, modreq, modopt, &buf);
802 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
803 encode_reflection_type (assembly, pt, &buf);
806 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
807 for (i = 0; i < notypes; ++i) {
808 MonoReflectionType *pt;
810 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
811 encode_reflection_type (assembly, pt, &buf);
814 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
815 sigbuffer_free (&buf);
820 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
822 MonoDynamicTable *table;
824 guint32 idx, sig_idx;
825 guint nl = mono_array_length (ilgen->locals);
829 sigbuffer_init (&buf, 32);
830 sigbuffer_add_value (&buf, 0x07);
831 sigbuffer_add_value (&buf, nl);
832 for (i = 0; i < nl; ++i) {
833 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
836 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
838 encode_reflection_type (assembly, lb->type, &buf);
840 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
841 sigbuffer_free (&buf);
843 if (assembly->standalonesig_cache == NULL)
844 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
845 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
849 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
850 idx = table->next_idx ++;
852 alloc_table (table, table->rows);
853 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
855 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
857 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
863 method_count_clauses (MonoReflectionILGen *ilgen)
865 guint32 num_clauses = 0;
868 MonoILExceptionInfo *ex_info;
869 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
870 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
871 if (ex_info->handlers)
872 num_clauses += mono_array_length (ex_info->handlers);
880 static MonoExceptionClause*
881 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
883 MonoExceptionClause *clauses;
884 MonoExceptionClause *clause;
885 MonoILExceptionInfo *ex_info;
886 MonoILExceptionBlock *ex_block;
887 guint32 finally_start;
888 int i, j, clause_index;;
890 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
893 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
894 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
895 finally_start = ex_info->start + ex_info->len;
896 if (!ex_info->handlers)
898 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
899 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
900 clause = &(clauses [clause_index]);
902 clause->flags = ex_block->type;
903 clause->try_offset = ex_info->start;
905 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
906 clause->try_len = finally_start - ex_info->start;
908 clause->try_len = ex_info->len;
909 clause->handler_offset = ex_block->start;
910 clause->handler_len = ex_block->len;
911 if (ex_block->extype) {
912 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
914 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
915 clause->data.filter_offset = ex_block->filter_offset;
917 clause->data.filter_offset = 0;
919 finally_start = ex_block->start + ex_block->len;
929 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
935 gint32 num_locals = 0;
936 gint32 num_exception = 0;
939 char fat_header [12];
942 guint32 local_sig = 0;
943 guint32 header_size = 12;
946 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
947 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
951 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
953 code = mb->ilgen->code;
954 code_size = mb->ilgen->code_len;
955 max_stack = mb->ilgen->max_stack;
956 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
957 if (mb->ilgen->ex_handlers)
958 num_exception = method_count_clauses (mb->ilgen);
962 char *name = mono_string_to_utf8 (mb->name);
963 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
964 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
967 mono_raise_exception (exception);
970 code_size = mono_array_length (code);
971 max_stack = 8; /* we probably need to run a verifier on the code... */
974 stream_data_align (&assembly->code);
976 /* check for exceptions, maxstack, locals */
977 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
979 if (code_size < 64 && !(code_size & 1)) {
980 flags = (code_size << 2) | 0x2;
981 } else if (code_size < 32 && (code_size & 1)) {
982 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
986 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
987 /* add to the fixup todo list */
988 if (mb->ilgen && mb->ilgen->num_token_fixups)
989 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
990 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
991 return assembly->text_rva + idx;
995 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
997 * FIXME: need to set also the header size in fat_flags.
998 * (and more sects and init locals flags)
1002 fat_flags |= METHOD_HEADER_MORE_SECTS;
1003 if (mb->init_locals)
1004 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1005 fat_header [0] = fat_flags;
1006 fat_header [1] = (header_size / 4 ) << 4;
1007 short_value = GUINT16_TO_LE (max_stack);
1008 memcpy (fat_header + 2, &short_value, 2);
1009 int_value = GUINT32_TO_LE (code_size);
1010 memcpy (fat_header + 4, &int_value, 4);
1011 int_value = GUINT32_TO_LE (local_sig);
1012 memcpy (fat_header + 8, &int_value, 4);
1013 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1014 /* add to the fixup todo list */
1015 if (mb->ilgen && mb->ilgen->num_token_fixups)
1016 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1018 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1019 if (num_exception) {
1020 unsigned char sheader [4];
1021 MonoILExceptionInfo * ex_info;
1022 MonoILExceptionBlock * ex_block;
1025 stream_data_align (&assembly->code);
1026 /* always use fat format for now */
1027 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1028 num_exception *= 6 * sizeof (guint32);
1029 num_exception += 4; /* include the size of the header */
1030 sheader [1] = num_exception & 0xff;
1031 sheader [2] = (num_exception >> 8) & 0xff;
1032 sheader [3] = (num_exception >> 16) & 0xff;
1033 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1034 /* fat header, so we are already aligned */
1036 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1037 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1038 if (ex_info->handlers) {
1039 int finally_start = ex_info->start + ex_info->len;
1040 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1042 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1044 val = GUINT32_TO_LE (ex_block->type);
1045 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1047 val = GUINT32_TO_LE (ex_info->start);
1048 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1049 /* need fault, too, probably */
1050 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1051 val = GUINT32_TO_LE (finally_start - ex_info->start);
1053 val = GUINT32_TO_LE (ex_info->len);
1054 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1055 /* handler offset */
1056 val = GUINT32_TO_LE (ex_block->start);
1057 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1059 val = GUINT32_TO_LE (ex_block->len);
1060 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1061 finally_start = ex_block->start + ex_block->len;
1062 if (ex_block->extype) {
1063 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1065 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1066 val = ex_block->filter_offset;
1070 val = GUINT32_TO_LE (val);
1071 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1072 /*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",
1073 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);*/
1076 g_error ("No clauses for ex info block %d", i);
1080 return assembly->text_rva + idx;
1084 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1087 MonoDynamicTable *table;
1090 table = &assembly->tables [table_idx];
1092 g_assert (col < table->columns);
1094 values = table->values + table->columns;
1095 for (i = 1; i <= table->rows; ++i) {
1096 if (values [col] == token)
1098 values += table->columns;
1104 * LOCKING: Acquires the loader lock.
1106 static MonoCustomAttrInfo*
1107 lookup_custom_attr (MonoImage *image, gpointer member)
1109 MonoCustomAttrInfo* res;
1111 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1116 return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1120 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1122 /* FIXME: Need to do more checks */
1123 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1124 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1126 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1133 static MonoCustomAttrInfo*
1134 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1136 int i, index, count, not_visible;
1137 MonoCustomAttrInfo *ainfo;
1138 MonoReflectionCustomAttr *cattr;
1142 /* FIXME: check in assembly the Run flag is set */
1144 count = mono_array_length (cattrs);
1146 /* Skip nonpublic attributes since MS.NET seems to do the same */
1147 /* FIXME: This needs to be done more globally */
1149 for (i = 0; i < count; ++i) {
1150 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1151 if (!custom_attr_visible (image, cattr))
1154 count -= not_visible;
1156 ainfo = image_g_malloc0 (alloc_img, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1158 ainfo->image = image;
1159 ainfo->num_attrs = count;
1160 ainfo->cached = alloc_img != NULL;
1162 for (i = 0; i < count; ++i) {
1163 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1164 if (custom_attr_visible (image, cattr)) {
1165 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1166 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1167 ainfo->attrs [index].ctor = cattr->ctor->method;
1168 ainfo->attrs [index].data = saved;
1169 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1178 * LOCKING: Acquires the loader lock.
1181 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1183 MonoCustomAttrInfo *ainfo, *tmp;
1185 if (!cattrs || !mono_array_length (cattrs))
1188 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1190 mono_loader_lock ();
1191 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1193 mono_custom_attrs_free (tmp);
1194 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1195 mono_loader_unlock ();
1200 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1207 * idx is the table index of the object
1208 * type is one of MONO_CUSTOM_ATTR_*
1211 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1213 MonoDynamicTable *table;
1214 MonoReflectionCustomAttr *cattr;
1216 guint32 count, i, token;
1218 char *p = blob_size;
1220 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1223 count = mono_array_length (cattrs);
1224 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1225 table->rows += count;
1226 alloc_table (table, table->rows);
1227 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1228 idx <<= MONO_CUSTOM_ATTR_BITS;
1230 for (i = 0; i < count; ++i) {
1231 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1232 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1233 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1234 type = mono_metadata_token_index (token);
1235 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1236 switch (mono_metadata_token_table (token)) {
1237 case MONO_TABLE_METHOD:
1238 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1240 case MONO_TABLE_MEMBERREF:
1241 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1244 g_warning ("got wrong token in custom attr");
1247 values [MONO_CUSTOM_ATTR_TYPE] = type;
1249 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1250 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1251 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1252 values += MONO_CUSTOM_ATTR_SIZE;
1258 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1260 MonoDynamicTable *table;
1262 guint32 count, i, idx;
1263 MonoReflectionPermissionSet *perm;
1268 count = mono_array_length (permissions);
1269 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1270 table->rows += count;
1271 alloc_table (table, table->rows);
1273 for (i = 0; i < mono_array_length (permissions); ++i) {
1274 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1276 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1278 idx = mono_metadata_token_index (parent_token);
1279 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1280 switch (mono_metadata_token_table (parent_token)) {
1281 case MONO_TABLE_TYPEDEF:
1282 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1284 case MONO_TABLE_METHOD:
1285 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1287 case MONO_TABLE_ASSEMBLY:
1288 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1291 g_assert_not_reached ();
1294 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1295 values [MONO_DECL_SECURITY_PARENT] = idx;
1296 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1303 * Fill in the MethodDef and ParamDef tables for a method.
1304 * This is used for both normal methods and constructors.
1307 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1309 MonoDynamicTable *table;
1313 /* room in this table is already allocated */
1314 table = &assembly->tables [MONO_TABLE_METHOD];
1315 *mb->table_idx = table->next_idx ++;
1316 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1317 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1318 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1319 values [MONO_METHOD_FLAGS] = mb->attrs;
1320 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1321 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1322 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1324 table = &assembly->tables [MONO_TABLE_PARAM];
1325 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1327 mono_image_add_decl_security (assembly,
1328 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1331 MonoDynamicTable *mtable;
1334 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1335 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1338 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1339 if (mono_array_get (mb->pinfo, gpointer, i))
1342 table->rows += count;
1343 alloc_table (table, table->rows);
1344 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1345 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1346 MonoReflectionParamBuilder *pb;
1347 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1348 values [MONO_PARAM_FLAGS] = pb->attrs;
1349 values [MONO_PARAM_SEQUENCE] = i;
1350 if (pb->name != NULL) {
1351 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1353 values [MONO_PARAM_NAME] = 0;
1355 values += MONO_PARAM_SIZE;
1356 if (pb->marshal_info) {
1358 alloc_table (mtable, mtable->rows);
1359 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1360 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1361 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1363 pb->table_idx = table->next_idx++;
1364 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1365 guint32 field_type = 0;
1366 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1368 alloc_table (mtable, mtable->rows);
1369 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1370 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1371 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1372 mvalues [MONO_CONSTANT_TYPE] = field_type;
1373 mvalues [MONO_CONSTANT_PADDING] = 0;
1381 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1383 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1385 rmb->ilgen = mb->ilgen;
1386 rmb->rtype = mb->rtype;
1387 rmb->parameters = mb->parameters;
1388 rmb->generic_params = mb->generic_params;
1389 rmb->generic_container = mb->generic_container;
1390 rmb->opt_types = NULL;
1391 rmb->pinfo = mb->pinfo;
1392 rmb->attrs = mb->attrs;
1393 rmb->iattrs = mb->iattrs;
1394 rmb->call_conv = mb->call_conv;
1395 rmb->code = mb->code;
1396 rmb->type = mb->type;
1397 rmb->name = mb->name;
1398 rmb->table_idx = &mb->table_idx;
1399 rmb->init_locals = mb->init_locals;
1400 rmb->skip_visibility = FALSE;
1401 rmb->return_modreq = mb->return_modreq;
1402 rmb->return_modopt = mb->return_modopt;
1403 rmb->param_modreq = mb->param_modreq;
1404 rmb->param_modopt = mb->param_modopt;
1405 rmb->permissions = mb->permissions;
1406 rmb->mhandle = mb->mhandle;
1411 rmb->charset = mb->charset;
1412 rmb->extra_flags = mb->extra_flags;
1413 rmb->native_cc = mb->native_cc;
1414 rmb->dllentry = mb->dllentry;
1420 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1422 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1424 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1426 rmb->ilgen = mb->ilgen;
1427 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1428 rmb->parameters = mb->parameters;
1429 rmb->generic_params = NULL;
1430 rmb->generic_container = NULL;
1431 rmb->opt_types = NULL;
1432 rmb->pinfo = mb->pinfo;
1433 rmb->attrs = mb->attrs;
1434 rmb->iattrs = mb->iattrs;
1435 rmb->call_conv = mb->call_conv;
1437 rmb->type = mb->type;
1438 rmb->name = mono_string_new (mono_domain_get (), name);
1439 rmb->table_idx = &mb->table_idx;
1440 rmb->init_locals = mb->init_locals;
1441 rmb->skip_visibility = FALSE;
1442 rmb->return_modreq = NULL;
1443 rmb->return_modopt = NULL;
1444 rmb->param_modreq = mb->param_modreq;
1445 rmb->param_modopt = mb->param_modopt;
1446 rmb->permissions = mb->permissions;
1447 rmb->mhandle = mb->mhandle;
1453 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1455 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1457 rmb->ilgen = mb->ilgen;
1458 rmb->rtype = mb->rtype;
1459 rmb->parameters = mb->parameters;
1460 rmb->generic_params = NULL;
1461 rmb->generic_container = NULL;
1462 rmb->opt_types = NULL;
1464 rmb->attrs = mb->attrs;
1466 rmb->call_conv = mb->call_conv;
1468 rmb->type = (MonoObject *) mb->owner;
1469 rmb->name = mb->name;
1470 rmb->table_idx = NULL;
1471 rmb->init_locals = mb->init_locals;
1472 rmb->skip_visibility = mb->skip_visibility;
1473 rmb->return_modreq = NULL;
1474 rmb->return_modopt = NULL;
1475 rmb->param_modreq = NULL;
1476 rmb->param_modopt = NULL;
1477 rmb->permissions = NULL;
1478 rmb->mhandle = mb->mhandle;
1484 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1486 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1487 MonoDynamicTable *table;
1491 if (!mb->override_method)
1494 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1496 alloc_table (table, table->rows);
1497 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1498 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1499 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1501 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1502 switch (mono_metadata_token_table (tok)) {
1503 case MONO_TABLE_MEMBERREF:
1504 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1506 case MONO_TABLE_METHOD:
1507 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1510 g_assert_not_reached ();
1512 values [MONO_METHODIMPL_DECLARATION] = tok;
1516 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1518 MonoDynamicTable *table;
1520 ReflectionMethodBuilder rmb;
1523 reflection_methodbuilder_from_method_builder (&rmb, mb);
1525 mono_image_basic_method (&rmb, assembly);
1526 mb->table_idx = *rmb.table_idx;
1528 if (mb->dll) { /* It's a P/Invoke method */
1530 /* map CharSet values to on-disk values */
1531 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1532 int extra_flags = mb->extra_flags;
1533 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1535 alloc_table (table, table->rows);
1536 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1538 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1539 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1541 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1543 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1544 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1545 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1546 table = &assembly->tables [MONO_TABLE_MODULEREF];
1548 alloc_table (table, table->rows);
1549 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1550 values [MONO_IMPLMAP_SCOPE] = table->rows;
1554 if (mb->generic_params) {
1555 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1556 table->rows += mono_array_length (mb->generic_params);
1557 alloc_table (table, table->rows);
1558 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1559 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1561 mono_image_get_generic_param_info (
1562 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1569 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1571 ReflectionMethodBuilder rmb;
1573 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1575 mono_image_basic_method (&rmb, assembly);
1576 mb->table_idx = *rmb.table_idx;
1580 type_get_fully_qualified_name (MonoType *type)
1582 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1586 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1590 klass = my_mono_class_from_mono_type (type);
1592 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1593 ta = klass->image->assembly;
1594 if (ta->dynamic || (ta == ass)) {
1595 if (klass->generic_class || klass->generic_container)
1596 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1597 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1599 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1602 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1606 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1611 if (!assembly->save)
1614 sigbuffer_init (&buf, 32);
1616 sigbuffer_add_value (&buf, 0x06);
1617 /* encode custom attributes before the type */
1618 /* FIXME: This should probably go in encode_type () */
1619 if (type->num_mods) {
1620 for (i = 0; i < type->num_mods; ++i) {
1621 if (type->modifiers [i].required)
1622 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1624 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1625 sigbuffer_add_value (&buf, type->modifiers [i].token);
1628 encode_type (assembly, type, &buf);
1629 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1630 sigbuffer_free (&buf);
1635 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1640 sigbuffer_init (&buf, 32);
1642 sigbuffer_add_value (&buf, 0x06);
1643 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1644 /* encode custom attributes before the type */
1645 encode_reflection_type (assembly, fb->type, &buf);
1646 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1647 sigbuffer_free (&buf);
1652 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1653 char blob_size [64];
1654 char *b = blob_size;
1657 guint32 idx = 0, len = 0, dummy = 0;
1659 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1660 guint32 fpa_double [2];
1665 p = buf = g_malloc (64);
1667 *ret_type = MONO_TYPE_CLASS;
1669 box_val = (char*)&dummy;
1671 box_val = ((char*)val) + sizeof (MonoObject);
1672 *ret_type = val->vtable->klass->byval_arg.type;
1675 switch (*ret_type) {
1676 case MONO_TYPE_BOOLEAN:
1681 case MONO_TYPE_CHAR:
1698 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1699 fpa_p = (guint32*)box_val;
1700 fpa_double [0] = fpa_p [1];
1701 fpa_double [1] = fpa_p [0];
1702 box_val = (char*)fpa_double;
1706 case MONO_TYPE_VALUETYPE:
1707 if (val->vtable->klass->enumtype) {
1708 *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1711 g_error ("we can't encode valuetypes");
1712 case MONO_TYPE_CLASS:
1714 case MONO_TYPE_STRING: {
1715 MonoString *str = (MonoString*)val;
1716 /* there is no signature */
1717 len = str->length * 2;
1718 mono_metadata_encode_value (len, b, &b);
1719 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1721 char *swapped = g_malloc (2 * mono_string_length (str));
1722 const char *p = (const char*)mono_string_chars (str);
1724 swap_with_size (swapped, p, 2, mono_string_length (str));
1725 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1729 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1735 case MONO_TYPE_GENERICINST:
1736 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1739 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1742 /* there is no signature */
1743 mono_metadata_encode_value (len, b, &b);
1744 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1745 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1746 swap_with_size (blob_size, box_val, len, 1);
1747 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1749 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1757 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1762 sigbuffer_init (&buf, 32);
1764 sigbuffer_add_value (&buf, minfo->type);
1766 switch (minfo->type) {
1767 case MONO_NATIVE_BYVALTSTR:
1768 case MONO_NATIVE_BYVALARRAY:
1769 sigbuffer_add_value (&buf, minfo->count);
1771 case MONO_NATIVE_LPARRAY:
1772 if (minfo->eltype || minfo->has_size) {
1773 sigbuffer_add_value (&buf, minfo->eltype);
1774 if (minfo->has_size) {
1775 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1776 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1778 /* LAMESPEC: ElemMult is undocumented */
1779 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1783 case MONO_NATIVE_CUSTOM:
1785 str = mono_string_to_utf8 (minfo->guid);
1787 sigbuffer_add_value (&buf, len);
1788 sigbuffer_add_mem (&buf, str, len);
1791 sigbuffer_add_value (&buf, 0);
1793 /* native type name */
1794 sigbuffer_add_value (&buf, 0);
1795 /* custom marshaler type name */
1796 if (minfo->marshaltype || minfo->marshaltyperef) {
1797 if (minfo->marshaltyperef)
1798 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1800 str = mono_string_to_utf8 (minfo->marshaltype);
1802 sigbuffer_add_value (&buf, len);
1803 sigbuffer_add_mem (&buf, str, len);
1806 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1807 sigbuffer_add_value (&buf, 0);
1809 if (minfo->mcookie) {
1810 str = mono_string_to_utf8 (minfo->mcookie);
1812 sigbuffer_add_value (&buf, len);
1813 sigbuffer_add_mem (&buf, str, len);
1816 sigbuffer_add_value (&buf, 0);
1822 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1823 sigbuffer_free (&buf);
1828 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1830 MonoDynamicTable *table;
1833 /* maybe this fixup should be done in the C# code */
1834 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1835 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1836 table = &assembly->tables [MONO_TABLE_FIELD];
1837 fb->table_idx = table->next_idx ++;
1838 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1839 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1840 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1841 values [MONO_FIELD_FLAGS] = fb->attrs;
1842 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1844 if (fb->offset != -1) {
1845 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1847 alloc_table (table, table->rows);
1848 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1849 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1850 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1852 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1853 guint32 field_type = 0;
1854 table = &assembly->tables [MONO_TABLE_CONSTANT];
1856 alloc_table (table, table->rows);
1857 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1858 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1859 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1860 values [MONO_CONSTANT_TYPE] = field_type;
1861 values [MONO_CONSTANT_PADDING] = 0;
1863 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1865 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1867 alloc_table (table, table->rows);
1868 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1869 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1871 * We store it in the code section because it's simpler for now.
1874 if (mono_array_length (fb->rva_data) >= 10)
1875 stream_data_align (&assembly->code);
1876 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1878 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1879 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1881 if (fb->marshal_info) {
1882 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1884 alloc_table (table, table->rows);
1885 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1886 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1887 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1892 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1895 guint32 nparams = 0;
1896 MonoReflectionMethodBuilder *mb = fb->get_method;
1897 MonoReflectionMethodBuilder *smb = fb->set_method;
1900 if (mb && mb->parameters)
1901 nparams = mono_array_length (mb->parameters);
1902 if (!mb && smb && smb->parameters)
1903 nparams = mono_array_length (smb->parameters) - 1;
1904 sigbuffer_init (&buf, 32);
1905 sigbuffer_add_byte (&buf, 0x08);
1906 sigbuffer_add_value (&buf, nparams);
1908 encode_reflection_type (assembly, mb->rtype, &buf);
1909 for (i = 0; i < nparams; ++i) {
1910 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1911 encode_reflection_type (assembly, pt, &buf);
1913 } else if (smb && smb->parameters) {
1914 /* the property type is the last param */
1915 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1916 for (i = 0; i < nparams; ++i) {
1917 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1918 encode_reflection_type (assembly, pt, &buf);
1921 encode_reflection_type (assembly, fb->type, &buf);
1924 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1925 sigbuffer_free (&buf);
1930 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1932 MonoDynamicTable *table;
1934 guint num_methods = 0;
1938 * we need to set things in the following tables:
1939 * PROPERTYMAP (info already filled in _get_type_info ())
1940 * PROPERTY (rows already preallocated in _get_type_info ())
1941 * METHOD (method info already done with the generic method code)
1944 table = &assembly->tables [MONO_TABLE_PROPERTY];
1945 pb->table_idx = table->next_idx ++;
1946 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1947 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1948 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1949 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1951 /* FIXME: we still don't handle 'other' methods */
1952 if (pb->get_method) num_methods ++;
1953 if (pb->set_method) num_methods ++;
1955 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1956 table->rows += num_methods;
1957 alloc_table (table, table->rows);
1959 if (pb->get_method) {
1960 semaidx = table->next_idx ++;
1961 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1962 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1963 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1964 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1966 if (pb->set_method) {
1967 semaidx = table->next_idx ++;
1968 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1969 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1970 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1971 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1976 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1978 MonoDynamicTable *table;
1980 guint num_methods = 0;
1984 * we need to set things in the following tables:
1985 * EVENTMAP (info already filled in _get_type_info ())
1986 * EVENT (rows already preallocated in _get_type_info ())
1987 * METHOD (method info already done with the generic method code)
1990 table = &assembly->tables [MONO_TABLE_EVENT];
1991 eb->table_idx = table->next_idx ++;
1992 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1993 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1994 values [MONO_EVENT_FLAGS] = eb->attrs;
1995 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1998 * FIXME: we still don't handle 'other' methods
2000 if (eb->add_method) num_methods ++;
2001 if (eb->remove_method) num_methods ++;
2002 if (eb->raise_method) num_methods ++;
2004 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2005 table->rows += num_methods;
2006 alloc_table (table, table->rows);
2008 if (eb->add_method) {
2009 semaidx = table->next_idx ++;
2010 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2011 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2012 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2013 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2015 if (eb->remove_method) {
2016 semaidx = table->next_idx ++;
2017 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2018 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2019 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2020 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2022 if (eb->raise_method) {
2023 semaidx = table->next_idx ++;
2024 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2025 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2026 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2027 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2032 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2034 MonoDynamicTable *table;
2035 guint32 num_constraints, i;
2039 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2040 num_constraints = gparam->iface_constraints ?
2041 mono_array_length (gparam->iface_constraints) : 0;
2042 table->rows += num_constraints;
2043 if (gparam->base_type)
2045 alloc_table (table, table->rows);
2047 if (gparam->base_type) {
2048 table_idx = table->next_idx ++;
2049 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2051 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2052 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2053 assembly, gparam->base_type->type);
2056 for (i = 0; i < num_constraints; i++) {
2057 MonoReflectionType *constraint = mono_array_get (
2058 gparam->iface_constraints, gpointer, i);
2060 table_idx = table->next_idx ++;
2061 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2063 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2064 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2065 assembly, constraint->type);
2070 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2072 GenericParamTableEntry *entry;
2075 * The GenericParam table must be sorted according to the `owner' field.
2076 * We need to do this sorting prior to writing the GenericParamConstraint
2077 * table, since we have to use the final GenericParam table indices there
2078 * and they must also be sorted.
2081 entry = g_new0 (GenericParamTableEntry, 1);
2082 entry->owner = owner;
2083 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2084 MOVING_GC_REGISTER (&entry->gparam);
2085 entry->gparam = gparam;
2087 g_ptr_array_add (assembly->gen_params, entry);
2091 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2093 MonoDynamicTable *table;
2094 MonoGenericParam *param;
2098 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2099 table_idx = table->next_idx ++;
2100 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2102 param = entry->gparam->type.type->data.generic_param;
2104 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2105 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2106 values [MONO_GENERICPARAM_NUMBER] = param->num;
2107 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2109 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2111 encode_constraints (entry->gparam, table_idx, assembly);
2115 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2117 MonoDynamicTable *table;
2120 guint32 cols [MONO_ASSEMBLY_SIZE];
2124 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2127 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2128 table = &assembly->tables [MONO_TABLE_MODULEREF];
2129 token = table->next_idx ++;
2131 alloc_table (table, table->rows);
2132 values = table->values + token * MONO_MODULEREF_SIZE;
2133 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2135 token <<= MONO_RESOLTION_SCOPE_BITS;
2136 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2137 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2142 if (image->assembly->dynamic)
2144 memset (cols, 0, sizeof (cols));
2146 /* image->assembly->image is the manifest module */
2147 image = image->assembly->image;
2148 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2151 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2152 token = table->next_idx ++;
2154 alloc_table (table, table->rows);
2155 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2156 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2157 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2158 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2159 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2160 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2161 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2162 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2163 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2165 if (strcmp ("", image->assembly->aname.culture)) {
2166 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2167 image->assembly->aname.culture);
2170 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2171 guchar pubtoken [9];
2173 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2174 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2176 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2178 token <<= MONO_RESOLTION_SCOPE_BITS;
2179 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2180 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2185 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2187 MonoDynamicTable *table;
2192 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2195 sigbuffer_init (&buf, 32);
2196 switch (type->type) {
2197 case MONO_TYPE_FNPTR:
2199 case MONO_TYPE_SZARRAY:
2200 case MONO_TYPE_ARRAY:
2202 case MONO_TYPE_MVAR:
2203 case MONO_TYPE_GENERICINST:
2204 encode_type (assembly, type, &buf);
2206 case MONO_TYPE_CLASS:
2207 case MONO_TYPE_VALUETYPE: {
2208 MonoClass *k = mono_class_from_mono_type (type);
2209 if (!k || !k->generic_container) {
2210 sigbuffer_free (&buf);
2213 encode_type (assembly, type, &buf);
2217 sigbuffer_free (&buf);
2221 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2222 if (assembly->save) {
2223 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2224 alloc_table (table, table->rows + 1);
2225 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2226 values [MONO_TYPESPEC_SIGNATURE] = token;
2228 sigbuffer_free (&buf);
2230 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2231 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2237 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2239 MonoDynamicTable *table;
2241 guint32 token, scope, enclosing;
2244 /* if the type requires a typespec, we must try that first*/
2245 if (try_typespec && (token = create_typespec (assembly, type)))
2247 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2250 klass = my_mono_class_from_mono_type (type);
2252 klass = mono_class_from_mono_type (type);
2255 * If it's in the same module and not a generic type parameter:
2257 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2258 (type->type != MONO_TYPE_MVAR)) {
2259 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2260 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2261 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2265 if (klass->nested_in) {
2266 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2267 /* get the typeref idx of the enclosing type */
2268 enclosing >>= MONO_TYPEDEFORREF_BITS;
2269 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2271 scope = resolution_scope_from_image (assembly, klass->image);
2273 table = &assembly->tables [MONO_TABLE_TYPEREF];
2274 if (assembly->save) {
2275 alloc_table (table, table->rows + 1);
2276 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2277 values [MONO_TYPEREF_SCOPE] = scope;
2278 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2279 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2281 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2282 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2284 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2289 * Despite the name, we handle also TypeSpec (with the above helper).
2292 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2294 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2298 * Insert a memberef row into the metadata: the token that point to the memberref
2299 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2300 * mono_image_get_fieldref_token()).
2301 * The sig param is an index to an already built signature.
2304 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2306 MonoDynamicTable *table;
2308 guint32 token, pclass;
2311 parent = mono_image_typedef_or_ref (assembly, type);
2312 switch (parent & MONO_TYPEDEFORREF_MASK) {
2313 case MONO_TYPEDEFORREF_TYPEREF:
2314 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2316 case MONO_TYPEDEFORREF_TYPESPEC:
2317 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2319 case MONO_TYPEDEFORREF_TYPEDEF:
2320 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2323 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2326 /* extract the index */
2327 parent >>= MONO_TYPEDEFORREF_BITS;
2329 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2331 if (assembly->save) {
2332 alloc_table (table, table->rows + 1);
2333 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2334 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2335 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2336 values [MONO_MEMBERREF_SIGNATURE] = sig;
2339 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2346 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2349 MonoMethodSignature *sig;
2351 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2353 if (create_typespec) {
2354 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2359 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2360 if (token && !create_typespec)
2363 g_assert (!method->is_inflated);
2366 * A methodref signature can't contain an unmanaged calling convention.
2368 sig = mono_metadata_signature_dup (mono_method_signature (method));
2369 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2370 sig->call_convention = MONO_CALL_DEFAULT;
2371 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2372 method->name, method_encode_signature (assembly, sig));
2374 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2377 if (create_typespec) {
2378 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2379 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2380 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2382 if (assembly->save) {
2385 alloc_table (table, table->rows + 1);
2386 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2387 values [MONO_METHODSPEC_METHOD] = token;
2388 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2391 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2393 /*methodspec and memberef tokens are diferent, */
2394 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2401 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2404 ReflectionMethodBuilder rmb;
2407 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2411 name = mono_string_to_utf8 (method->name);
2412 reflection_methodbuilder_from_method_builder (&rmb, method);
2415 * A methodref signature can't contain an unmanaged calling convention.
2416 * Since some flags are encoded as part of call_conv, we need to check against it.
2418 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2419 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2420 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2421 name, method_builder_encode_signature (assembly, &rmb));
2424 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2429 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2430 const gchar *name, guint32 sig)
2432 MonoDynamicTable *table;
2436 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2438 if (assembly->save) {
2439 alloc_table (table, table->rows + 1);
2440 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2441 values [MONO_MEMBERREF_CLASS] = original;
2442 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2443 values [MONO_MEMBERREF_SIGNATURE] = sig;
2446 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2453 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2457 guint32 nparams = mono_array_length (mb->generic_params);
2460 if (!assembly->save)
2463 sigbuffer_init (&buf, 32);
2465 sigbuffer_add_value (&buf, 0xa);
2466 sigbuffer_add_value (&buf, nparams);
2468 for (i = 0; i < nparams; i++) {
2469 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2470 sigbuffer_add_value (&buf, i);
2473 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2474 sigbuffer_free (&buf);
2479 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2481 MonoDynamicTable *table;
2483 guint32 token, mtoken = 0;
2485 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2489 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2491 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2492 switch (mono_metadata_token_table (mtoken)) {
2493 case MONO_TABLE_MEMBERREF:
2494 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2496 case MONO_TABLE_METHOD:
2497 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2500 g_assert_not_reached ();
2503 if (assembly->save) {
2504 alloc_table (table, table->rows + 1);
2505 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2506 values [MONO_METHODSPEC_METHOD] = mtoken;
2507 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2510 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2513 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2518 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2522 if (mb->generic_params && create_methodspec)
2523 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2525 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2529 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2530 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2535 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2538 ReflectionMethodBuilder rmb;
2541 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2545 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2547 name = mono_string_to_utf8 (rmb.name);
2548 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2549 name, method_builder_encode_signature (assembly, &rmb));
2552 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2557 is_field_on_inst (MonoClassField *field)
2559 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2563 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2566 get_field_on_inst_generic_type (MonoClassField *field)
2568 MonoDynamicGenericClass *dgclass;
2571 g_assert (is_field_on_inst (field));
2573 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2574 field_index = field - dgclass->fields;
2576 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2577 return dgclass->field_generic_types [field_index];
2581 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2585 MonoClassField *field;
2587 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2590 g_assert (f->field->parent);
2593 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2594 int index = field - field->parent->fields;
2595 type = field->parent->generic_class->container_class->fields [index].type;
2597 if (is_field_on_inst (f->field))
2598 type = get_field_on_inst_generic_type (f->field);
2600 type = f->field->type;
2602 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2603 mono_field_get_name (f->field),
2604 fieldref_encode_signature (assembly, type));
2605 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2610 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2614 MonoGenericClass *gclass;
2615 MonoDynamicGenericClass *dgclass;
2616 MonoReflectionFieldBuilder *fb = f->fb;
2619 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2622 klass = mono_class_from_mono_type (f->inst->type.type);
2623 gclass = f->inst->type.type->data.generic_class;
2624 g_assert (gclass->is_dynamic);
2625 dgclass = (MonoDynamicGenericClass *) gclass;
2627 name = mono_string_to_utf8 (fb->name);
2628 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2629 field_encode_signature (assembly, fb));
2631 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2636 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2640 MonoGenericClass *gclass;
2641 MonoDynamicGenericClass *dgclass;
2642 MonoReflectionCtorBuilder *cb = c->cb;
2643 ReflectionMethodBuilder rmb;
2646 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2648 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2651 klass = mono_class_from_mono_type (c->inst->type.type);
2652 gclass = c->inst->type.type->data.generic_class;
2653 g_assert (gclass->is_dynamic);
2654 dgclass = (MonoDynamicGenericClass *) gclass;
2656 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2658 name = mono_string_to_utf8 (rmb.name);
2660 sig = method_builder_encode_signature (assembly, &rmb);
2662 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2665 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2670 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2674 MonoGenericClass *gclass;
2675 MonoReflectionMethodBuilder *mb = m->mb;
2676 ReflectionMethodBuilder rmb;
2679 if (create_methodspec && mb->generic_params)
2681 g_assert_not_reached ();
2683 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2686 klass = mono_class_from_mono_type (m->inst->type.type);
2687 gclass = m->inst->type.type->data.generic_class;
2688 g_assert (gclass->is_dynamic);
2690 reflection_methodbuilder_from_method_builder (&rmb, mb);
2692 name = mono_string_to_utf8 (rmb.name);
2694 sig = method_builder_encode_signature (assembly, &rmb);
2696 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2699 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2704 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2708 guint32 nparams = context->method_inst->type_argc;
2711 if (!assembly->save)
2714 sigbuffer_init (&buf, 32);
2716 * FIXME: vararg, explicit_this, differenc call_conv values...
2718 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2719 sigbuffer_add_value (&buf, nparams);
2721 for (i = 0; i < nparams; i++)
2722 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2724 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2725 sigbuffer_free (&buf);
2730 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2732 MonoDynamicTable *table;
2734 guint32 token, mtoken = 0, sig;
2735 MonoMethodInflated *imethod;
2736 MonoMethod *declaring;
2738 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2740 g_assert (method->is_inflated);
2741 imethod = (MonoMethodInflated *) method;
2742 declaring = imethod->declaring;
2744 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2745 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2747 if (!mono_method_signature (declaring)->generic_param_count)
2750 switch (mono_metadata_token_table (mtoken)) {
2751 case MONO_TABLE_MEMBERREF:
2752 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2754 case MONO_TABLE_METHOD:
2755 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2758 g_assert_not_reached ();
2761 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2763 if (assembly->save) {
2764 alloc_table (table, table->rows + 1);
2765 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2766 values [MONO_METHODSPEC_METHOD] = mtoken;
2767 values [MONO_METHODSPEC_SIGNATURE] = sig;
2770 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2777 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2779 MonoMethodInflated *imethod;
2782 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2786 g_assert (method->is_inflated);
2787 imethod = (MonoMethodInflated *) method;
2789 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2790 token = method_encode_methodspec (assembly, method);
2792 guint32 sig = method_encode_signature (
2793 assembly, mono_method_signature (imethod->declaring));
2794 token = mono_image_get_memberref_token (
2795 assembly, &method->klass->byval_arg, method->name, sig);
2798 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2803 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2805 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2808 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2809 token = mono_image_get_memberref_token (
2810 assembly, &m->klass->byval_arg, m->name, sig);
2816 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2818 MonoDynamicTable *table;
2826 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2827 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2828 * Because of this, we must not insert it into the `typeref' hash table.
2831 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2835 sigbuffer_init (&buf, 32);
2837 g_assert (tb->generic_params);
2838 klass = mono_class_from_mono_type (tb->type.type);
2840 if (tb->generic_container)
2841 mono_reflection_create_generic_class (tb);
2843 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2844 g_assert (klass->generic_container);
2845 sigbuffer_add_value (&buf, klass->byval_arg.type);
2846 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2848 count = mono_array_length (tb->generic_params);
2849 sigbuffer_add_value (&buf, count);
2850 for (i = 0; i < count; i++) {
2851 MonoReflectionGenericParam *gparam;
2853 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2855 encode_type (assembly, gparam->type.type, &buf);
2858 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2860 if (assembly->save) {
2861 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2862 alloc_table (table, table->rows + 1);
2863 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2864 values [MONO_TYPESPEC_SIGNATURE] = token;
2866 sigbuffer_free (&buf);
2868 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2869 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2875 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2878 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2880 int i, count, len, pos;
2885 count += mono_array_length (modreq);
2887 count += mono_array_length (modopt);
2890 return mono_metadata_type_dup (NULL, type);
2892 len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
2894 memcpy (t, type, len);
2896 t->num_mods = count;
2899 for (i = 0; i < mono_array_length (modreq); ++i) {
2900 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
2901 t->modifiers [pos].required = 1;
2902 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2907 for (i = 0; i < mono_array_length (modopt); ++i) {
2908 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
2909 t->modifiers [pos].required = 0;
2910 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2919 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2921 MonoDynamicTable *table;
2923 MonoType *custom = NULL;
2925 guint32 token, pclass, parent, sig;
2928 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2932 klass = mono_class_from_mono_type (fb->typeb->type);
2933 name = mono_string_to_utf8 (fb->name);
2935 /* fb->type does not include the custom modifiers */
2936 /* FIXME: We should do this in one place when a fieldbuilder is created */
2937 if (fb->modreq || fb->modopt) {
2938 custom = add_custom_modifiers (assembly, fb->type->type, fb->modreq, fb->modopt);
2939 sig = fieldref_encode_signature (assembly, custom);
2942 sig = fieldref_encode_signature (assembly, fb->type->type);
2945 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2946 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2948 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2949 parent >>= MONO_TYPEDEFORREF_BITS;
2951 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2953 if (assembly->save) {
2954 alloc_table (table, table->rows + 1);
2955 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2956 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2957 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2958 values [MONO_MEMBERREF_SIGNATURE] = sig;
2961 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2963 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2969 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2976 if (!assembly->save)
2979 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2980 g_assert (helper->type == 2);
2982 if (helper->arguments)
2983 nargs = mono_array_length (helper->arguments);
2987 size = 10 + (nargs * 10);
2989 sigbuffer_init (&buf, 32);
2991 /* Encode calling convention */
2992 /* Change Any to Standard */
2993 if ((helper->call_conv & 0x03) == 0x03)
2994 helper->call_conv = 0x01;
2995 /* explicit_this implies has_this */
2996 if (helper->call_conv & 0x40)
2997 helper->call_conv &= 0x20;
2999 if (helper->call_conv == 0) { /* Unmanaged */
3000 idx = helper->unmanaged_call_conv - 1;
3003 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3004 if (helper->call_conv & 0x02) /* varargs */
3008 sigbuffer_add_byte (&buf, idx);
3009 sigbuffer_add_value (&buf, nargs);
3010 encode_reflection_type (assembly, helper->return_type, &buf);
3011 for (i = 0; i < nargs; ++i) {
3012 MonoArray *modreqs = NULL;
3013 MonoArray *modopts = NULL;
3014 MonoReflectionType *pt;
3016 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3017 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3018 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3019 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3021 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3022 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3023 encode_reflection_type (assembly, pt, &buf);
3025 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3026 sigbuffer_free (&buf);
3032 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3035 MonoDynamicTable *table;
3038 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3039 idx = table->next_idx ++;
3041 alloc_table (table, table->rows);
3042 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3044 values [MONO_STAND_ALONE_SIGNATURE] =
3045 mono_reflection_encode_sighelper (assembly, helper);
3051 reflection_cc_to_file (int call_conv) {
3052 switch (call_conv & 0x3) {
3054 case 1: return MONO_CALL_DEFAULT;
3055 case 2: return MONO_CALL_VARARG;
3057 g_assert_not_reached ();
3064 MonoMethodSignature *sig;
3070 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3075 MonoMethodSignature *sig;
3078 name = mono_string_to_utf8 (m->name);
3079 nparams = mono_array_length (m->parameters);
3080 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
3082 sig->sentinelpos = -1;
3083 sig->call_convention = reflection_cc_to_file (m->call_conv);
3084 sig->param_count = nparams;
3085 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
3086 for (i = 0; i < nparams; ++i) {
3087 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
3088 sig->params [i] = t->type;
3091 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3093 if (strcmp (name, am->name) == 0 &&
3094 mono_metadata_type_equal (am->parent, m->parent->type) &&
3095 mono_metadata_signature_equal (am->sig, sig)) {
3098 m->table_idx = am->token & 0xffffff;
3102 am = g_new0 (ArrayMethod, 1);
3105 am->parent = m->parent->type;
3106 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3107 method_encode_signature (assembly, sig));
3108 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3109 m->table_idx = am->token & 0xffffff;
3114 * Insert into the metadata tables all the info about the TypeBuilder tb.
3115 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3118 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3120 MonoDynamicTable *table;
3122 int i, is_object = 0, is_system = 0;
3125 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3126 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3127 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3128 n = mono_string_to_utf8 (tb->name);
3129 if (strcmp (n, "Object") == 0)
3131 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3133 n = mono_string_to_utf8 (tb->nspace);
3134 if (strcmp (n, "System") == 0)
3136 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3138 if (tb->parent && !(is_system && is_object) &&
3139 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3140 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
3142 values [MONO_TYPEDEF_EXTENDS] = 0;
3144 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3145 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3148 * if we have explicitlayout or sequentiallayouts, output data in the
3149 * ClassLayout table.
3151 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3152 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3153 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3155 alloc_table (table, table->rows);
3156 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3157 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3158 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3159 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3162 /* handle interfaces */
3163 if (tb->interfaces) {
3164 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3166 table->rows += mono_array_length (tb->interfaces);
3167 alloc_table (table, table->rows);
3168 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3169 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3170 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3171 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3172 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3173 values += MONO_INTERFACEIMPL_SIZE;
3179 table = &assembly->tables [MONO_TABLE_FIELD];
3180 table->rows += tb->num_fields;
3181 alloc_table (table, table->rows);
3182 for (i = 0; i < tb->num_fields; ++i)
3183 mono_image_get_field_info (
3184 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3187 /* handle constructors */
3189 table = &assembly->tables [MONO_TABLE_METHOD];
3190 table->rows += mono_array_length (tb->ctors);
3191 alloc_table (table, table->rows);
3192 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3193 mono_image_get_ctor_info (domain,
3194 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3197 /* handle methods */
3199 table = &assembly->tables [MONO_TABLE_METHOD];
3200 table->rows += tb->num_methods;
3201 alloc_table (table, table->rows);
3202 for (i = 0; i < tb->num_methods; ++i)
3203 mono_image_get_method_info (
3204 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3207 /* Do the same with properties etc.. */
3208 if (tb->events && mono_array_length (tb->events)) {
3209 table = &assembly->tables [MONO_TABLE_EVENT];
3210 table->rows += mono_array_length (tb->events);
3211 alloc_table (table, table->rows);
3212 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3214 alloc_table (table, table->rows);
3215 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3216 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3217 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3218 for (i = 0; i < mono_array_length (tb->events); ++i)
3219 mono_image_get_event_info (
3220 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3222 if (tb->properties && mono_array_length (tb->properties)) {
3223 table = &assembly->tables [MONO_TABLE_PROPERTY];
3224 table->rows += mono_array_length (tb->properties);
3225 alloc_table (table, table->rows);
3226 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3228 alloc_table (table, table->rows);
3229 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3230 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3231 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3232 for (i = 0; i < mono_array_length (tb->properties); ++i)
3233 mono_image_get_property_info (
3234 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3237 /* handle generic parameters */
3238 if (tb->generic_params) {
3239 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3240 table->rows += mono_array_length (tb->generic_params);
3241 alloc_table (table, table->rows);
3242 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3243 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3245 mono_image_get_generic_param_info (
3246 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3250 mono_image_add_decl_security (assembly,
3251 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3254 MonoDynamicTable *ntable;
3256 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3257 ntable->rows += mono_array_length (tb->subtypes);
3258 alloc_table (ntable, ntable->rows);
3259 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3261 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3262 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3264 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3265 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3266 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3267 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3268 mono_string_to_utf8 (tb->name), tb->table_idx,
3269 ntable->next_idx, ntable->rows);*/
3270 values += MONO_NESTED_CLASS_SIZE;
3277 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3281 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3283 if (!type->subtypes)
3286 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3287 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3288 collect_types (types, subtype);
3293 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3295 if ((*type1)->table_idx < (*type2)->table_idx)
3298 if ((*type1)->table_idx > (*type2)->table_idx)
3305 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3310 for (i = 0; i < mono_array_length (pinfo); ++i) {
3311 MonoReflectionParamBuilder *pb;
3312 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3315 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3320 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3323 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3325 for (i = 0; i < tb->num_fields; ++i) {
3326 MonoReflectionFieldBuilder* fb;
3327 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3328 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3332 for (i = 0; i < mono_array_length (tb->events); ++i) {
3333 MonoReflectionEventBuilder* eb;
3334 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3335 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3338 if (tb->properties) {
3339 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3340 MonoReflectionPropertyBuilder* pb;
3341 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3342 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3346 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3347 MonoReflectionCtorBuilder* cb;
3348 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3349 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3350 params_add_cattrs (assembly, cb->pinfo);
3355 for (i = 0; i < tb->num_methods; ++i) {
3356 MonoReflectionMethodBuilder* mb;
3357 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3358 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3359 params_add_cattrs (assembly, mb->pinfo);
3364 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3365 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3370 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3374 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3376 if (moduleb->global_methods) {
3377 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3378 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3379 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3380 params_add_cattrs (assembly, mb->pinfo);
3384 if (moduleb->global_fields) {
3385 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3386 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3387 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3391 if (moduleb->types) {
3392 for (i = 0; i < moduleb->num_types; ++i)
3393 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3398 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3400 MonoDynamicTable *table;
3404 char *b = blob_size;
3407 table = &assembly->tables [MONO_TABLE_FILE];
3409 alloc_table (table, table->rows);
3410 values = table->values + table->next_idx * MONO_FILE_SIZE;
3411 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3412 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3413 if (module->image->dynamic) {
3414 /* This depends on the fact that the main module is emitted last */
3415 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3416 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3419 path = g_strdup (module->image->name);
3421 mono_sha1_get_digest_from_file (path, hash);
3424 mono_metadata_encode_value (20, b, &b);
3425 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3426 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3431 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3433 MonoDynamicTable *table;
3436 table = &assembly->tables [MONO_TABLE_MODULE];
3437 mb->table_idx = table->next_idx ++;
3438 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3439 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3442 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3443 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3444 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3445 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3449 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3450 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3452 MonoDynamicTable *table;
3456 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3457 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3460 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3462 alloc_table (table, table->rows);
3463 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3465 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3466 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3467 if (klass->nested_in)
3468 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3470 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3471 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3472 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3474 res = table->next_idx;
3478 /* Emit nested types */
3479 if (klass->ext && klass->ext->nested_classes) {
3482 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3483 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3490 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3491 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3496 klass = mono_class_from_mono_type (tb->type.type);
3498 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3500 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3501 parent_index, assembly);
3505 * We need to do this ourselves since klass->nested_classes is not set up.
3508 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3509 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3514 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3515 guint32 module_index, MonoDynamicImage *assembly)
3517 MonoImage *image = module->image;
3521 t = &image->tables [MONO_TABLE_TYPEDEF];
3523 for (i = 0; i < t->rows; ++i) {
3524 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3526 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3527 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3532 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3534 MonoDynamicTable *table;
3540 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3542 if (assemblyb->type_forwarders) {
3543 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3544 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3550 klass = mono_class_from_mono_type (t->type);
3552 scope = resolution_scope_from_image (assembly, klass->image);
3553 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3554 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3557 alloc_table (table, table->rows);
3558 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3560 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3561 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3562 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3563 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3564 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3571 #define align_pointer(base,p)\
3573 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3575 (p) += 4 - (__diff & 3);\
3579 compare_constants (const void *a, const void *b)
3581 const guint32 *a_values = a;
3582 const guint32 *b_values = b;
3583 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3587 compare_semantics (const void *a, const void *b)
3589 const guint32 *a_values = a;
3590 const guint32 *b_values = b;
3591 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3594 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3598 compare_custom_attrs (const void *a, const void *b)
3600 const guint32 *a_values = a;
3601 const guint32 *b_values = b;
3603 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3607 compare_field_marshal (const void *a, const void *b)
3609 const guint32 *a_values = a;
3610 const guint32 *b_values = b;
3612 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3616 compare_nested (const void *a, const void *b)
3618 const guint32 *a_values = a;
3619 const guint32 *b_values = b;
3621 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3625 compare_genericparam (const void *a, const void *b)
3627 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3628 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3630 if ((*b_entry)->owner == (*a_entry)->owner)
3632 (*a_entry)->gparam->type.type->data.generic_param->num -
3633 (*b_entry)->gparam->type.type->data.generic_param->num;
3635 return (*a_entry)->owner - (*b_entry)->owner;
3639 compare_declsecurity_attrs (const void *a, const void *b)
3641 const guint32 *a_values = a;
3642 const guint32 *b_values = b;
3644 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3648 compare_interface_impl (const void *a, const void *b)
3650 const guint32 *a_values = a;
3651 const guint32 *b_values = b;
3653 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3657 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3661 pad_heap (MonoDynamicStream *sh)
3663 if (sh->index & 3) {
3664 int sz = 4 - (sh->index & 3);
3665 memset (sh->data + sh->index, 0, sz);
3672 MonoDynamicStream *stream;
3676 * build_compressed_metadata() fills in the blob of data that represents the
3677 * raw metadata as it will be saved in the PE file. The five streams are output
3678 * and the metadata tables are comnpressed from the guint32 array representation,
3679 * to the compressed on-disk format.
3682 build_compressed_metadata (MonoDynamicImage *assembly)
3684 MonoDynamicTable *table;
3686 guint64 valid_mask = 0;
3687 guint64 sorted_mask;
3688 guint32 heapt_size = 0;
3689 guint32 meta_size = 256; /* allow for header and other stuff */
3690 guint32 table_offset;
3691 guint32 ntables = 0;
3697 struct StreamDesc stream_desc [5];
3699 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3700 for (i = 0; i < assembly->gen_params->len; i++){
3701 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3702 write_generic_param_entry (assembly, entry);
3705 stream_desc [0].name = "#~";
3706 stream_desc [0].stream = &assembly->tstream;
3707 stream_desc [1].name = "#Strings";
3708 stream_desc [1].stream = &assembly->sheap;
3709 stream_desc [2].name = "#US";
3710 stream_desc [2].stream = &assembly->us;
3711 stream_desc [3].name = "#Blob";
3712 stream_desc [3].stream = &assembly->blob;
3713 stream_desc [4].name = "#GUID";
3714 stream_desc [4].stream = &assembly->guid;
3716 /* tables that are sorted */
3717 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3718 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3719 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3720 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3721 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3722 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3723 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3725 /* Compute table sizes */
3726 /* the MonoImage has already been created in mono_image_basic_init() */
3727 meta = &assembly->image;
3729 /* sizes should be multiple of 4 */
3730 pad_heap (&assembly->blob);
3731 pad_heap (&assembly->guid);
3732 pad_heap (&assembly->sheap);
3733 pad_heap (&assembly->us);
3735 /* Setup the info used by compute_sizes () */
3736 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3737 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3738 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3740 meta_size += assembly->blob.index;
3741 meta_size += assembly->guid.index;
3742 meta_size += assembly->sheap.index;
3743 meta_size += assembly->us.index;
3745 for (i=0; i < MONO_TABLE_NUM; ++i)
3746 meta->tables [i].rows = assembly->tables [i].rows;
3748 for (i = 0; i < MONO_TABLE_NUM; i++){
3749 if (meta->tables [i].rows == 0)
3751 valid_mask |= (guint64)1 << i;
3753 meta->tables [i].row_size = mono_metadata_compute_size (
3754 meta, i, &meta->tables [i].size_bitfield);
3755 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3757 heapt_size += 24; /* #~ header size */
3758 heapt_size += ntables * 4;
3759 /* make multiple of 4 */
3762 meta_size += heapt_size;
3763 meta->raw_metadata = g_malloc0 (meta_size);
3764 p = (unsigned char*)meta->raw_metadata;
3765 /* the metadata signature */
3766 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3767 /* version numbers and 4 bytes reserved */
3768 int16val = (guint16*)p;
3769 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3770 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3772 /* version string */
3773 int32val = (guint32*)p;
3774 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3776 memcpy (p, meta->version, strlen (meta->version));
3777 p += GUINT32_FROM_LE (*int32val);
3778 align_pointer (meta->raw_metadata, p);
3779 int16val = (guint16*)p;
3780 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3781 *int16val = GUINT16_TO_LE (5); /* number of streams */
3785 * write the stream info.
3787 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3788 table_offset += 3; table_offset &= ~3;
3790 assembly->tstream.index = heapt_size;
3791 for (i = 0; i < 5; ++i) {
3792 int32val = (guint32*)p;
3793 stream_desc [i].stream->offset = table_offset;
3794 *int32val++ = GUINT32_TO_LE (table_offset);
3795 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3796 table_offset += GUINT32_FROM_LE (*int32val);
3797 table_offset += 3; table_offset &= ~3;
3799 strcpy ((char*)p, stream_desc [i].name);
3800 p += strlen (stream_desc [i].name) + 1;
3801 align_pointer (meta->raw_metadata, p);
3804 * now copy the data, the table stream header and contents goes first.
3806 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3807 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3808 int32val = (guint32*)p;
3809 *int32val = GUINT32_TO_LE (0); /* reserved */
3812 if (mono_framework_version () > 1) {
3813 *p++ = 2; /* version */
3816 *p++ = 1; /* version */
3820 if (meta->idx_string_wide)
3822 if (meta->idx_guid_wide)
3824 if (meta->idx_blob_wide)
3827 *p++ = 1; /* reserved */
3828 int64val = (guint64*)p;
3829 *int64val++ = GUINT64_TO_LE (valid_mask);
3830 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3832 int32val = (guint32*)p;
3833 for (i = 0; i < MONO_TABLE_NUM; i++){
3834 if (meta->tables [i].rows == 0)
3836 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3838 p = (unsigned char*)int32val;
3840 /* sort the tables that still need sorting */
3841 table = &assembly->tables [MONO_TABLE_CONSTANT];
3843 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3844 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3846 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3847 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3849 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3850 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3852 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3853 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3855 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3856 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3857 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3859 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3860 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3862 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3864 /* compress the tables */
3865 for (i = 0; i < MONO_TABLE_NUM; i++){
3868 guint32 bitfield = meta->tables [i].size_bitfield;
3869 if (!meta->tables [i].rows)
3871 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3872 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3873 meta->tables [i].base = (char*)p;
3874 for (row = 1; row <= meta->tables [i].rows; ++row) {
3875 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3876 for (col = 0; col < assembly->tables [i].columns; ++col) {
3877 switch (mono_metadata_table_size (bitfield, col)) {
3879 *p++ = values [col];
3882 *p++ = values [col] & 0xff;
3883 *p++ = (values [col] >> 8) & 0xff;
3886 *p++ = values [col] & 0xff;
3887 *p++ = (values [col] >> 8) & 0xff;
3888 *p++ = (values [col] >> 16) & 0xff;
3889 *p++ = (values [col] >> 24) & 0xff;
3892 g_assert_not_reached ();
3896 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3899 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3900 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3901 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3902 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3903 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3905 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3909 * Some tables in metadata need to be sorted according to some criteria, but
3910 * when methods and fields are first created with reflection, they may be assigned a token
3911 * that doesn't correspond to the final token they will get assigned after the sorting.
3912 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3913 * with the reflection objects that represent them. Once all the tables are set up, the
3914 * reflection objects will contains the correct table index. fixup_method() will fixup the
3915 * tokens for the method with ILGenerator @ilgen.
3918 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3920 guint32 code_idx = GPOINTER_TO_UINT (value);
3921 MonoReflectionILTokenInfo *iltoken;
3922 MonoReflectionFieldBuilder *field;
3923 MonoReflectionCtorBuilder *ctor;
3924 MonoReflectionMethodBuilder *method;
3925 MonoReflectionTypeBuilder *tb;
3926 MonoReflectionArrayMethod *am;
3928 unsigned char *target;
3930 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3931 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3932 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3933 switch (target [3]) {
3934 case MONO_TABLE_FIELD:
3935 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3936 field = (MonoReflectionFieldBuilder *)iltoken->member;
3937 idx = field->table_idx;
3938 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3939 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3940 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3942 g_assert_not_reached ();
3945 case MONO_TABLE_METHOD:
3946 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3947 method = (MonoReflectionMethodBuilder *)iltoken->member;
3948 idx = method->table_idx;
3949 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3950 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3951 idx = ctor->table_idx;
3952 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3953 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3954 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3955 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3957 g_assert_not_reached ();
3960 case MONO_TABLE_TYPEDEF:
3961 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3962 g_assert_not_reached ();
3963 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3964 idx = tb->table_idx;
3966 case MONO_TABLE_MEMBERREF:
3967 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3968 am = (MonoReflectionArrayMethod*)iltoken->member;
3969 idx = am->table_idx;
3970 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3971 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3972 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3973 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3974 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3975 g_assert (m->klass->generic_class || m->klass->generic_container);
3977 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3979 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3980 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3981 g_assert (is_field_on_inst (f));
3983 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3984 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3986 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3988 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
3990 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
3993 g_assert_not_reached ();
3996 case MONO_TABLE_METHODSPEC:
3997 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3998 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3999 g_assert (mono_method_signature (m)->generic_param_count);
4001 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4004 g_assert_not_reached ();
4008 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4010 target [0] = idx & 0xff;
4011 target [1] = (idx >> 8) & 0xff;
4012 target [2] = (idx >> 16) & 0xff;
4019 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4020 * value is not known when the table is emitted.
4023 fixup_cattrs (MonoDynamicImage *assembly)
4025 MonoDynamicTable *table;
4027 guint32 type, i, idx, token;
4030 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4032 for (i = 0; i < table->rows; ++i) {
4033 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4035 type = values [MONO_CUSTOM_ATTR_TYPE];
4036 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4037 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4038 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4039 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4042 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4043 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4044 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4045 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4052 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4054 MonoDynamicTable *table;
4057 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4059 alloc_table (table, table->rows);
4060 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4061 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4062 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4063 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4064 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4069 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4071 MonoDynamicTable *table;
4075 char *b = blob_size;
4077 guint32 idx, offset;
4079 if (rsrc->filename) {
4080 name = mono_string_to_utf8 (rsrc->filename);
4081 sname = g_path_get_basename (name);
4083 table = &assembly->tables [MONO_TABLE_FILE];
4085 alloc_table (table, table->rows);
4086 values = table->values + table->next_idx * MONO_FILE_SIZE;
4087 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4088 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4091 mono_sha1_get_digest_from_file (name, hash);
4092 mono_metadata_encode_value (20, b, &b);
4093 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4094 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4096 idx = table->next_idx++;
4098 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4104 data = mono_array_addr (rsrc->data, char, 0);
4105 len = mono_array_length (rsrc->data);
4111 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4112 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4113 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4114 mono_image_add_stream_data (&assembly->resources, data, len);
4118 * The entry should be emitted into the MANIFESTRESOURCE table of
4119 * the main module, but that needs to reference the FILE table
4120 * which isn't emitted yet.
4127 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4131 set_version_from_string (MonoString *version, guint32 *values)
4133 gchar *ver, *p, *str;
4136 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4137 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4138 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4139 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4142 ver = str = mono_string_to_utf8 (version);
4143 for (i = 0; i < 4; ++i) {
4144 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4150 /* handle Revision and Build */
4160 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4164 char *b = blob_size;
4169 len = mono_array_length (pkey);
4170 mono_metadata_encode_value (len, b, &b);
4171 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4172 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4174 assembly->public_key = g_malloc (len);
4175 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4176 assembly->public_key_len = len;
4178 /* Special case: check for ECMA key (16 bytes) */
4179 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4180 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4181 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4182 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4183 /* minimum key size (in 2.0) is 384 bits */
4184 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4186 /* FIXME - verifier */
4187 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4188 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4190 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4196 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4198 MonoDynamicTable *table;
4199 MonoDynamicImage *assembly;
4200 MonoReflectionAssemblyBuilder *assemblyb;
4204 guint32 module_index;
4206 assemblyb = moduleb->assemblyb;
4207 assembly = moduleb->dynamic_image;
4208 domain = mono_object_domain (assemblyb);
4210 /* Emit ASSEMBLY table */
4211 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4212 alloc_table (table, 1);
4213 values = table->values + MONO_ASSEMBLY_SIZE;
4214 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4215 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4216 if (assemblyb->culture) {
4217 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4219 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4221 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4222 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4223 set_version_from_string (assemblyb->version, values);
4225 /* Emit FILE + EXPORTED_TYPE table */
4227 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4229 MonoReflectionModuleBuilder *file_module =
4230 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4231 if (file_module != moduleb) {
4232 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4234 if (file_module->types) {
4235 for (j = 0; j < file_module->num_types; ++j) {
4236 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4237 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4242 if (assemblyb->loaded_modules) {
4243 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4244 MonoReflectionModule *file_module =
4245 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4246 mono_image_fill_file_table (domain, file_module, assembly);
4248 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4251 if (assemblyb->type_forwarders)
4252 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4254 /* Emit MANIFESTRESOURCE table */
4256 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4258 MonoReflectionModuleBuilder *file_module =
4259 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4260 /* The table for the main module is emitted later */
4261 if (file_module != moduleb) {
4263 if (file_module->resources) {
4264 int len = mono_array_length (file_module->resources);
4265 for (j = 0; j < len; ++j) {
4266 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4267 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4274 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4277 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4278 * for the modulebuilder @moduleb.
4279 * At the end of the process, method and field tokens are fixed up and the
4280 * on-disk compressed metadata representation is created.
4283 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4285 MonoDynamicTable *table;
4286 MonoDynamicImage *assembly;
4287 MonoReflectionAssemblyBuilder *assemblyb;
4293 assemblyb = moduleb->assemblyb;
4294 assembly = moduleb->dynamic_image;
4295 domain = mono_object_domain (assemblyb);
4297 if (assembly->text_rva)
4300 assembly->text_rva = START_TEXT_RVA;
4302 if (moduleb->is_main) {
4303 mono_image_emit_manifest (moduleb);
4306 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4307 table->rows = 1; /* .<Module> */
4309 alloc_table (table, table->rows);
4311 * Set the first entry.
4313 values = table->values + table->columns;
4314 values [MONO_TYPEDEF_FLAGS] = 0;
4315 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4316 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4317 values [MONO_TYPEDEF_EXTENDS] = 0;
4318 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4319 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4322 * handle global methods
4323 * FIXME: test what to do when global methods are defined in multiple modules.
4325 if (moduleb->global_methods) {
4326 table = &assembly->tables [MONO_TABLE_METHOD];
4327 table->rows += mono_array_length (moduleb->global_methods);
4328 alloc_table (table, table->rows);
4329 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4330 mono_image_get_method_info (
4331 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4333 if (moduleb->global_fields) {
4334 table = &assembly->tables [MONO_TABLE_FIELD];
4335 table->rows += mono_array_length (moduleb->global_fields);
4336 alloc_table (table, table->rows);
4337 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4338 mono_image_get_field_info (
4339 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4342 table = &assembly->tables [MONO_TABLE_MODULE];
4343 alloc_table (table, 1);
4344 mono_image_fill_module_table (domain, moduleb, assembly);
4346 /* Collect all types into a list sorted by their table_idx */
4347 types = g_ptr_array_new ();
4350 for (i = 0; i < moduleb->num_types; ++i) {
4351 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4352 collect_types (types, type);
4355 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4356 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4357 table->rows += types->len;
4358 alloc_table (table, table->rows);
4361 * Emit type names + namespaces at one place inside the string heap,
4362 * so load_class_names () needs to touch fewer pages.
4364 for (i = 0; i < types->len; ++i) {
4365 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4366 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4368 for (i = 0; i < types->len; ++i) {
4369 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4370 string_heap_insert_mstring (&assembly->sheap, tb->name);
4373 for (i = 0; i < types->len; ++i) {
4374 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4375 mono_image_get_type_info (domain, type, assembly);
4379 * table->rows is already set above and in mono_image_fill_module_table.
4381 /* add all the custom attributes at the end, once all the indexes are stable */
4382 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4384 /* CAS assembly permissions */
4385 if (assemblyb->permissions_minimum)
4386 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4387 if (assemblyb->permissions_optional)
4388 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4389 if (assemblyb->permissions_refused)
4390 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4392 module_add_cattrs (assembly, moduleb);
4395 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4397 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4398 * the final tokens and don't need another fixup pass. */
4400 if (moduleb->global_methods) {
4401 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4402 MonoReflectionMethodBuilder *mb = mono_array_get (
4403 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4404 mono_image_add_methodimpl (assembly, mb);
4408 for (i = 0; i < types->len; ++i) {
4409 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4410 if (type->methods) {
4411 for (j = 0; j < type->num_methods; ++j) {
4412 MonoReflectionMethodBuilder *mb = mono_array_get (
4413 type->methods, MonoReflectionMethodBuilder*, j);
4415 mono_image_add_methodimpl (assembly, mb);
4420 g_ptr_array_free (types, TRUE);
4422 fixup_cattrs (assembly);
4425 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4428 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4430 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4433 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4435 #ifndef DISABLE_REFLECTION_EMIT
4438 * mono_image_insert_string:
4439 * @module: module builder object
4442 * Insert @str into the user string stream of @module.
4445 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4447 MonoDynamicImage *assembly;
4452 MONO_ARCH_SAVE_REGS;
4454 if (!module->dynamic_image)
4455 mono_image_module_basic_init (module);
4457 assembly = module->dynamic_image;
4459 if (assembly->save) {
4460 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4461 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4462 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4464 char *swapped = g_malloc (2 * mono_string_length (str));
4465 const char *p = (const char*)mono_string_chars (str);
4467 swap_with_size (swapped, p, 2, mono_string_length (str));
4468 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4472 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4474 mono_image_add_stream_data (&assembly->us, "", 1);
4476 idx = assembly->us.index ++;
4479 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4481 return MONO_TOKEN_STRING | idx;
4485 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4490 klass = obj->vtable->klass;
4491 if (strcmp (klass->name, "MonoMethod") == 0) {
4492 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4493 MonoMethodSignature *sig, *old;
4494 guint32 sig_token, parent;
4497 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4499 nargs = mono_array_length (opt_param_types);
4500 old = mono_method_signature (method);
4501 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4503 sig->hasthis = old->hasthis;
4504 sig->explicit_this = old->explicit_this;
4505 sig->call_convention = old->call_convention;
4506 sig->generic_param_count = old->generic_param_count;
4507 sig->param_count = old->param_count + nargs;
4508 sig->sentinelpos = old->param_count;
4509 sig->ret = old->ret;
4511 for (i = 0; i < old->param_count; i++)
4512 sig->params [i] = old->params [i];
4514 for (i = 0; i < nargs; i++) {
4515 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4516 sig->params [old->param_count + i] = rt->type;
4519 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4520 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4521 parent >>= MONO_TYPEDEFORREF_BITS;
4523 parent <<= MONO_MEMBERREF_PARENT_BITS;
4524 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4526 sig_token = method_encode_signature (assembly, sig);
4527 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4528 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4529 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4530 ReflectionMethodBuilder rmb;
4531 guint32 parent, sig;
4534 reflection_methodbuilder_from_method_builder (&rmb, mb);
4535 rmb.opt_types = opt_param_types;
4537 sig = method_builder_encode_signature (assembly, &rmb);
4539 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4540 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4542 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4543 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4545 name = mono_string_to_utf8 (rmb.name);
4546 token = mono_image_get_varargs_method_token (
4547 assembly, parent, name, sig);
4550 g_error ("requested method token for %s\n", klass->name);
4557 * mono_image_create_token:
4558 * @assembly: a dynamic assembly
4560 * @register_token: Whenever to register the token in the assembly->tokens hash.
4562 * Get a token to insert in the IL code stream for the given MemberInfo.
4563 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4564 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4568 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4569 gboolean create_methodspec, gboolean register_token)
4574 klass = obj->vtable->klass;
4575 if (strcmp (klass->name, "MethodBuilder") == 0) {
4576 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4577 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4579 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4580 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4582 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4583 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4584 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4585 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4586 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4588 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4589 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4591 token = mono_image_get_ctorbuilder_token (assembly, mb);
4592 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4593 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4594 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4595 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4596 if (tb->generic_params) {
4597 token = mono_image_get_generic_field_token (assembly, fb);
4599 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4601 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4602 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4603 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4604 } else if (strcmp (klass->name, "MonoType") == 0) {
4605 MonoReflectionType *tb = (MonoReflectionType *)obj;
4606 MonoClass *mc = mono_class_from_mono_type (tb->type);
4607 token = mono_metadata_token_from_dor (
4608 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4609 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4610 MonoReflectionType *tb = (MonoReflectionType *)obj;
4611 token = mono_metadata_token_from_dor (
4612 mono_image_typedef_or_ref (assembly, tb->type));
4613 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4614 MonoReflectionType *tb = (MonoReflectionType *)obj;
4615 token = mono_metadata_token_from_dor (
4616 mono_image_typedef_or_ref (assembly, tb->type));
4617 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4618 strcmp (klass->name, "MonoMethod") == 0 ||
4619 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4620 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4621 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4622 if (m->method->is_inflated) {
4623 if (create_methodspec)
4624 token = mono_image_get_methodspec_token (assembly, m->method);
4626 token = mono_image_get_inflated_method_token (assembly, m->method);
4627 } else if ((m->method->klass->image == &assembly->image) &&
4628 !m->method->klass->generic_class) {
4629 static guint32 method_table_idx = 0xffffff;
4630 if (m->method->klass->wastypebuilder) {
4631 /* we use the same token as the one that was assigned
4632 * to the Methodbuilder.
4633 * FIXME: do the equivalent for Fields.
4635 token = m->method->token;
4638 * Each token should have a unique index, but the indexes are
4639 * assigned by managed code, so we don't know about them. An
4640 * easy solution is to count backwards...
4642 method_table_idx --;
4643 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4646 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4648 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4649 } else if (strcmp (klass->name, "MonoField") == 0) {
4650 MonoReflectionField *f = (MonoReflectionField *)obj;
4651 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4652 static guint32 field_table_idx = 0xffffff;
4654 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4656 token = mono_image_get_fieldref_token (assembly, f);
4658 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4659 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4660 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4661 token = mono_image_get_array_token (assembly, m);
4662 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4663 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4664 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4665 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4666 MonoReflectionType *tb = (MonoReflectionType *)obj;
4667 token = mono_metadata_token_from_dor (
4668 mono_image_typedef_or_ref (assembly, tb->type));
4669 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4670 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4671 token = mono_image_get_field_on_inst_token (assembly, f);
4672 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4673 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4674 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4675 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4676 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4677 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4679 g_error ("requested token for %s\n", klass->name);
4683 mono_image_register_token (assembly, token, obj);
4689 * mono_image_register_token:
4691 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4692 * the Module.ResolveXXXToken () methods to work.
4695 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4697 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4699 /* There could be multiple MethodInfo objects with the same token */
4700 //g_assert (prev == obj);
4702 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4706 #endif /* DISABLE_REFLECTION_EMIT */
4709 guint32 import_lookup_table;
4713 guint32 import_address_table_rva;
4721 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4723 static MonoDynamicImage*
4724 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4726 static const guchar entrycode [16] = {0xff, 0x25, 0};
4727 MonoDynamicImage *image;
4730 const char *version;
4732 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4733 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4735 version = mono_get_runtime_info ()->runtime_version;
4738 image = GC_MALLOC (sizeof (MonoDynamicImage));
4740 image = g_new0 (MonoDynamicImage, 1);
4743 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4745 /*g_print ("created image %p\n", image);*/
4746 /* keep in sync with image.c */
4747 image->image.name = assembly_name;
4748 image->image.assembly_name = image->image.name; /* they may be different */
4749 image->image.module_name = module_name;
4750 image->image.version = g_strdup (version);
4751 image->image.md_version_major = 1;
4752 image->image.md_version_minor = 1;
4753 image->image.dynamic = TRUE;
4755 image->image.references = g_new0 (MonoAssembly*, 1);
4756 image->image.references [0] = NULL;
4758 mono_image_init (&image->image);
4760 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4761 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4762 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4763 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4764 image->handleref = g_hash_table_new (NULL, NULL);
4765 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4766 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4767 image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4768 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4769 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4770 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4771 image->gen_params = g_ptr_array_new ();
4773 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4774 string_heap_init (&image->sheap);
4775 mono_image_add_stream_data (&image->us, "", 1);
4776 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4777 /* import tables... */
4778 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4779 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4780 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4781 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4782 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4783 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4784 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4785 stream_data_align (&image->code);
4787 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4789 for (i=0; i < MONO_TABLE_NUM; ++i) {
4790 image->tables [i].next_idx = 1;
4791 image->tables [i].columns = table_sizes [i];
4794 image->image.assembly = (MonoAssembly*)assembly;
4795 image->run = assembly->run;
4796 image->save = assembly->save;
4797 image->pe_kind = 0x1; /* ILOnly */
4798 image->machine = 0x14c; /* I386 */
4800 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4806 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4812 mono_dynamic_image_free (MonoDynamicImage *image)
4814 MonoDynamicImage *di = image;
4819 mono_g_hash_table_destroy (di->methodspec);
4821 g_hash_table_destroy (di->typespec);
4823 g_hash_table_destroy (di->typeref);
4825 g_hash_table_destroy (di->handleref);
4827 mono_g_hash_table_destroy (di->tokens);
4828 if (di->generic_def_objects)
4829 mono_g_hash_table_destroy (di->generic_def_objects);
4830 if (di->blob_cache) {
4831 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4832 g_hash_table_destroy (di->blob_cache);
4834 if (di->standalonesig_cache)
4835 g_hash_table_destroy (di->standalonesig_cache);
4836 for (list = di->array_methods; list; list = list->next) {
4837 ArrayMethod *am = (ArrayMethod *)list->data;
4842 g_list_free (di->array_methods);
4843 if (di->gen_params) {
4844 for (i = 0; i < di->gen_params->len; i++) {
4845 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4846 if (entry->gparam->type.type) {
4847 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4848 g_free ((char*)param->name);
4853 g_ptr_array_free (di->gen_params, TRUE);
4855 if (di->token_fixups)
4856 mono_g_hash_table_destroy (di->token_fixups);
4857 if (di->method_to_table_idx)
4858 g_hash_table_destroy (di->method_to_table_idx);
4859 if (di->field_to_table_idx)
4860 g_hash_table_destroy (di->field_to_table_idx);
4861 if (di->method_aux_hash)
4862 g_hash_table_destroy (di->method_aux_hash);
4863 g_free (di->strong_name);
4864 g_free (di->win32_res);
4866 g_free (di->public_key);
4868 /*g_print ("string heap destroy for image %p\n", di);*/
4869 mono_dynamic_stream_reset (&di->sheap);
4870 mono_dynamic_stream_reset (&di->code);
4871 mono_dynamic_stream_reset (&di->resources);
4872 mono_dynamic_stream_reset (&di->us);
4873 mono_dynamic_stream_reset (&di->blob);
4874 mono_dynamic_stream_reset (&di->tstream);
4875 mono_dynamic_stream_reset (&di->guid);
4876 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4877 g_free (di->tables [i].values);
4881 #ifndef DISABLE_REFLECTION_EMIT
4884 * mono_image_basic_init:
4885 * @assembly: an assembly builder object
4887 * Create the MonoImage that represents the assembly builder and setup some
4888 * of the helper hash table and the basic metadata streams.
4891 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4893 MonoDynamicAssembly *assembly;
4894 MonoDynamicImage *image;
4895 MonoDomain *domain = mono_object_domain (assemblyb);
4897 MONO_ARCH_SAVE_REGS;
4899 if (assemblyb->dynamic_assembly)
4903 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4905 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4908 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4910 assembly->assembly.ref_count = 1;
4911 assembly->assembly.dynamic = TRUE;
4912 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4913 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4914 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4915 if (assemblyb->culture)
4916 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4918 assembly->assembly.aname.culture = g_strdup ("");
4920 if (assemblyb->version) {
4921 char *vstr = mono_string_to_utf8 (assemblyb->version);
4922 char **version = g_strsplit (vstr, ".", 4);
4923 char **parts = version;
4924 assembly->assembly.aname.major = atoi (*parts++);
4925 assembly->assembly.aname.minor = atoi (*parts++);
4926 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4927 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4929 g_strfreev (version);
4932 assembly->assembly.aname.major = 0;
4933 assembly->assembly.aname.minor = 0;
4934 assembly->assembly.aname.build = 0;
4935 assembly->assembly.aname.revision = 0;
4938 assembly->run = assemblyb->access != 2;
4939 assembly->save = assemblyb->access != 1;
4941 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4942 image->initial_image = TRUE;
4943 assembly->assembly.aname.name = image->image.name;
4944 assembly->assembly.image = &image->image;
4946 mono_domain_assemblies_lock (domain);
4947 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4948 mono_domain_assemblies_unlock (domain);
4950 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4952 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4954 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4957 #endif /* DISABLE_REFLECTION_EMIT */
4959 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4962 calc_section_size (MonoDynamicImage *assembly)
4966 /* alignment constraints */
4967 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4968 g_assert ((assembly->code.index % 4) == 0);
4969 assembly->meta_size += 3;
4970 assembly->meta_size &= ~3;
4971 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4972 g_assert ((assembly->resources.index % 4) == 0);
4974 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4975 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4978 if (assembly->win32_res) {
4979 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4981 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4982 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4986 assembly->sections [MONO_SECTION_RELOC].size = 12;
4987 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4997 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5001 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5003 ResTreeNode *t1 = (ResTreeNode*)a;
5004 ResTreeNode *t2 = (ResTreeNode*)b;
5006 return t1->id - t2->id;
5010 * resource_tree_create:
5012 * Organize the resources into a resource tree.
5014 static ResTreeNode *
5015 resource_tree_create (MonoArray *win32_resources)
5017 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5021 tree = g_new0 (ResTreeNode, 1);
5023 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5024 MonoReflectionWin32Resource *win32_res =
5025 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5029 /* FIXME: BUG: this stores managed references in unmanaged memory */
5030 lang_node = g_new0 (ResTreeNode, 1);
5031 lang_node->id = win32_res->lang_id;
5032 lang_node->win32_res = win32_res;
5034 /* Create type node if neccesary */
5036 for (l = tree->children; l; l = l->next)
5037 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5038 type_node = (ResTreeNode*)l->data;
5043 type_node = g_new0 (ResTreeNode, 1);
5044 type_node->id = win32_res->res_type;
5047 * The resource types have to be sorted otherwise
5048 * Windows Explorer can't display the version information.
5050 tree->children = g_slist_insert_sorted (tree->children,
5051 type_node, resource_tree_compare_by_id);
5054 /* Create res node if neccesary */
5056 for (l = type_node->children; l; l = l->next)
5057 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5058 res_node = (ResTreeNode*)l->data;
5063 res_node = g_new0 (ResTreeNode, 1);
5064 res_node->id = win32_res->res_id;
5065 type_node->children = g_slist_append (type_node->children, res_node);
5068 res_node->children = g_slist_append (res_node->children, lang_node);
5075 * resource_tree_encode:
5077 * Encode the resource tree into the format used in the PE file.
5080 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5083 MonoPEResourceDir dir;
5084 MonoPEResourceDirEntry dir_entry;
5085 MonoPEResourceDataEntry data_entry;
5087 guint32 res_id_entries;
5090 * For the format of the resource directory, see the article
5091 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5095 memset (&dir, 0, sizeof (dir));
5096 memset (&dir_entry, 0, sizeof (dir_entry));
5097 memset (&data_entry, 0, sizeof (data_entry));
5099 g_assert (sizeof (dir) == 16);
5100 g_assert (sizeof (dir_entry) == 8);
5101 g_assert (sizeof (data_entry) == 16);
5103 node->offset = p - begin;
5105 /* IMAGE_RESOURCE_DIRECTORY */
5106 res_id_entries = g_slist_length (node->children);
5107 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5109 memcpy (p, &dir, sizeof (dir));
5112 /* Reserve space for entries */
5114 p += sizeof (dir_entry) * res_id_entries;
5116 /* Write children */
5117 for (l = node->children; l; l = l->next) {
5118 ResTreeNode *child = (ResTreeNode*)l->data;
5120 if (child->win32_res) {
5123 child->offset = p - begin;
5125 /* IMAGE_RESOURCE_DATA_ENTRY */
5126 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5127 size = mono_array_length (child->win32_res->res_data);
5128 data_entry.rde_size = GUINT32_TO_LE (size);
5130 memcpy (p, &data_entry, sizeof (data_entry));
5131 p += sizeof (data_entry);
5133 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5136 resource_tree_encode (child, begin, p, &p);
5140 /* IMAGE_RESOURCE_ENTRY */
5141 for (l = node->children; l; l = l->next) {
5142 ResTreeNode *child = (ResTreeNode*)l->data;
5144 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5145 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5147 memcpy (entries, &dir_entry, sizeof (dir_entry));
5148 entries += sizeof (dir_entry);
5155 resource_tree_free (ResTreeNode * node)
5158 for (list = node->children; list; list = list->next)
5159 resource_tree_free ((ResTreeNode*)list->data);
5160 g_slist_free(node->children);
5165 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5170 MonoReflectionWin32Resource *win32_res;
5173 if (!assemblyb->win32_resources)
5177 * Resources are stored in a three level tree inside the PE file.
5178 * - level one contains a node for each type of resource
5179 * - level two contains a node for each resource
5180 * - level three contains a node for each instance of a resource for a
5181 * specific language.
5184 tree = resource_tree_create (assemblyb->win32_resources);
5186 /* Estimate the size of the encoded tree */
5188 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5189 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5190 size += mono_array_length (win32_res->res_data);
5192 /* Directory structure */
5193 size += mono_array_length (assemblyb->win32_resources) * 256;
5194 p = buf = g_malloc (size);
5196 resource_tree_encode (tree, p, p, &p);
5198 g_assert (p - buf <= size);
5200 assembly->win32_res = g_malloc (p - buf);
5201 assembly->win32_res_size = p - buf;
5202 memcpy (assembly->win32_res, buf, p - buf);
5205 resource_tree_free (tree);
5209 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5211 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5214 p += sizeof (MonoPEResourceDir);
5215 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5216 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5217 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5218 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5219 fixup_resource_directory (res_section, child, rva);
5221 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5222 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5225 p += sizeof (MonoPEResourceDirEntry);
5230 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5233 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5234 g_error ("WriteFile returned %d\n", GetLastError ());
5238 * mono_image_create_pefile:
5239 * @mb: a module builder object
5241 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5242 * assembly->pefile where it can be easily retrieved later in chunks.
5245 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5247 MonoMSDOSHeader *msdos;
5248 MonoDotNetHeader *header;
5249 MonoSectionTable *section;
5250 MonoCLIHeader *cli_header;
5251 guint32 size, image_size, virtual_base, text_offset;
5252 guint32 header_start, section_start, file_offset, virtual_offset;
5253 MonoDynamicImage *assembly;
5254 MonoReflectionAssemblyBuilder *assemblyb;
5255 MonoDynamicStream pefile_stream = {0};
5256 MonoDynamicStream *pefile = &pefile_stream;
5258 guint32 *rva, value;
5260 static const unsigned char msheader[] = {
5261 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5262 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5265 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5266 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5267 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5268 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5271 assemblyb = mb->assemblyb;
5273 mono_image_basic_init (assemblyb);
5274 assembly = mb->dynamic_image;
5276 assembly->pe_kind = assemblyb->pe_kind;
5277 assembly->machine = assemblyb->machine;
5278 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5279 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5281 mono_image_build_metadata (mb);
5283 if (mb->is_main && assemblyb->resources) {
5284 int len = mono_array_length (assemblyb->resources);
5285 for (i = 0; i < len; ++i)
5286 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5289 if (mb->resources) {
5290 int len = mono_array_length (mb->resources);
5291 for (i = 0; i < len; ++i)
5292 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5295 build_compressed_metadata (assembly);
5298 assembly_add_win32_resources (assembly, assemblyb);
5300 nsections = calc_section_size (assembly);
5302 /* The DOS header and stub */
5303 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5304 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5306 /* the dotnet header */
5307 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5309 /* the section tables */
5310 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5312 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5313 virtual_offset = VIRT_ALIGN;
5316 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5317 if (!assembly->sections [i].size)
5320 file_offset += FILE_ALIGN - 1;
5321 file_offset &= ~(FILE_ALIGN - 1);
5322 virtual_offset += VIRT_ALIGN - 1;
5323 virtual_offset &= ~(VIRT_ALIGN - 1);
5325 assembly->sections [i].offset = file_offset;
5326 assembly->sections [i].rva = virtual_offset;
5328 file_offset += assembly->sections [i].size;
5329 virtual_offset += assembly->sections [i].size;
5330 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5333 file_offset += FILE_ALIGN - 1;
5334 file_offset &= ~(FILE_ALIGN - 1);
5336 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5338 /* back-patch info */
5339 msdos = (MonoMSDOSHeader*)pefile->data;
5340 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5342 header = (MonoDotNetHeader*)(pefile->data + header_start);
5343 header->pesig [0] = 'P';
5344 header->pesig [1] = 'E';
5346 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5347 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5348 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5349 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5350 if (assemblyb->pekind == 1) {
5352 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5355 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5358 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5360 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5361 header->pe.pe_major = 6;
5362 header->pe.pe_minor = 0;
5363 size = assembly->sections [MONO_SECTION_TEXT].size;
5364 size += FILE_ALIGN - 1;
5365 size &= ~(FILE_ALIGN - 1);
5366 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5367 size = assembly->sections [MONO_SECTION_RSRC].size;
5368 size += FILE_ALIGN - 1;
5369 size &= ~(FILE_ALIGN - 1);
5370 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5371 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5372 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5373 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5374 /* pe_rva_entry_point always at the beginning of the text section */
5375 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5377 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5378 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5379 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5380 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5381 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5382 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5383 size = section_start;
5384 size += FILE_ALIGN - 1;
5385 size &= ~(FILE_ALIGN - 1);
5386 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5388 size += VIRT_ALIGN - 1;
5389 size &= ~(VIRT_ALIGN - 1);
5390 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5393 // Translate the PEFileKind value to the value expected by the Windows loader
5399 // PEFileKinds.Dll == 1
5400 // PEFileKinds.ConsoleApplication == 2
5401 // PEFileKinds.WindowApplication == 3
5404 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5405 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5407 if (assemblyb->pekind == 3)
5412 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5414 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5415 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5416 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5417 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5418 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5419 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5421 /* fill data directory entries */
5423 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5424 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5426 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5427 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5429 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5430 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5431 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5432 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5433 /* patch entrypoint name */
5434 if (assemblyb->pekind == 1)
5435 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5437 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5438 /* patch imported function RVA name */
5439 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5440 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5442 /* the import table */
5443 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5444 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5445 /* patch imported dll RVA name and other entries in the dir */
5446 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5447 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5448 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5449 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5450 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5451 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5453 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5454 value = (assembly->text_rva + assembly->imp_names_offset);
5455 *p++ = (value) & 0xff;
5456 *p++ = (value >> 8) & (0xff);
5457 *p++ = (value >> 16) & (0xff);
5458 *p++ = (value >> 24) & (0xff);
5460 /* the CLI header info */
5461 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5462 cli_header->ch_size = GUINT32_FROM_LE (72);
5463 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5464 if (mono_framework_version () > 1)
5465 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5467 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5468 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5469 if (assemblyb->entry_point) {
5470 guint32 table_idx = 0;
5471 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5472 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5473 table_idx = methodb->table_idx;
5475 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5477 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5479 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5481 /* The embedded managed resources */
5482 text_offset = assembly->text_rva + assembly->code.index;
5483 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5484 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5485 text_offset += assembly->resources.index;
5486 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5487 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5488 text_offset += assembly->meta_size;
5489 if (assembly->strong_name_size) {
5490 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5491 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5492 text_offset += assembly->strong_name_size;
5495 /* write the section tables and section content */
5496 section = (MonoSectionTable*)(pefile->data + section_start);
5497 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5498 static const char section_names [][7] = {
5499 ".text", ".rsrc", ".reloc"
5501 if (!assembly->sections [i].size)
5503 strcpy (section->st_name, section_names [i]);
5504 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5505 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5506 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5507 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5508 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5509 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5510 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5514 checked_write_file (file, pefile->data, pefile->index);
5516 mono_dynamic_stream_reset (pefile);
5518 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5519 if (!assembly->sections [i].size)
5522 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5523 g_error ("SetFilePointer returned %d\n", GetLastError ());
5526 case MONO_SECTION_TEXT:
5527 /* patch entry point */
5528 p = (guchar*)(assembly->code.data + 2);
5529 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5530 *p++ = (value) & 0xff;
5531 *p++ = (value >> 8) & 0xff;
5532 *p++ = (value >> 16) & 0xff;
5533 *p++ = (value >> 24) & 0xff;
5535 checked_write_file (file, assembly->code.data, assembly->code.index);
5536 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5537 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5538 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5541 g_free (assembly->image.raw_metadata);
5543 case MONO_SECTION_RELOC: {
5547 guint16 type_and_offset;
5551 g_assert (sizeof (reloc) == 12);
5553 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5554 reloc.block_size = GUINT32_FROM_LE (12);
5557 * the entrypoint is always at the start of the text section
5558 * 3 is IMAGE_REL_BASED_HIGHLOW
5559 * 2 is patch_size_rva - text_rva
5561 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5564 checked_write_file (file, &reloc, sizeof (reloc));
5568 case MONO_SECTION_RSRC:
5569 if (assembly->win32_res) {
5571 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5572 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5573 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5577 g_assert_not_reached ();
5581 /* check that the file is properly padded */
5582 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5583 g_error ("SetFilePointer returned %d\n", GetLastError ());
5584 if (! SetEndOfFile (file))
5585 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5587 mono_dynamic_stream_reset (&assembly->code);
5588 mono_dynamic_stream_reset (&assembly->us);
5589 mono_dynamic_stream_reset (&assembly->blob);
5590 mono_dynamic_stream_reset (&assembly->guid);
5591 mono_dynamic_stream_reset (&assembly->sheap);
5593 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5594 g_hash_table_destroy (assembly->blob_cache);
5595 assembly->blob_cache = NULL;
5598 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5601 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5603 g_assert_not_reached ();
5606 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5608 #ifndef DISABLE_REFLECTION_EMIT
5610 MonoReflectionModule *
5611 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5615 MonoImageOpenStatus status;
5616 MonoDynamicAssembly *assembly;
5617 guint32 module_count;
5618 MonoImage **new_modules;
5619 gboolean *new_modules_loaded;
5621 name = mono_string_to_utf8 (fileName);
5623 image = mono_image_open (name, &status);
5626 if (status == MONO_IMAGE_ERROR_ERRNO)
5627 exc = mono_get_exception_file_not_found (fileName);
5629 exc = mono_get_exception_bad_image_format (name);
5631 mono_raise_exception (exc);
5636 assembly = ab->dynamic_assembly;
5637 image->assembly = (MonoAssembly*)assembly;
5639 module_count = image->assembly->image->module_count;
5640 new_modules = g_new0 (MonoImage *, module_count + 1);
5641 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5643 if (image->assembly->image->modules)
5644 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5645 if (image->assembly->image->modules_loaded)
5646 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5647 new_modules [module_count] = image;
5648 new_modules_loaded [module_count] = TRUE;
5649 mono_image_addref (image);
5651 g_free (image->assembly->image->modules);
5652 image->assembly->image->modules = new_modules;
5653 image->assembly->image->modules_loaded = new_modules_loaded;
5654 image->assembly->image->module_count ++;
5656 mono_assembly_load_references (image, &status);
5658 mono_image_close (image);
5659 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5662 return mono_module_get_object (mono_domain_get (), image);
5665 #endif /* DISABLE_REFLECTION_EMIT */
5668 * We need to return always the same object for MethodInfo, FieldInfo etc..
5669 * but we need to consider the reflected type.
5670 * type uses a different hash, since it uses custom hash/equal functions.
5675 MonoClass *refclass;
5679 reflected_equal (gconstpointer a, gconstpointer b) {
5680 const ReflectedEntry *ea = a;
5681 const ReflectedEntry *eb = b;
5683 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5687 reflected_hash (gconstpointer a) {
5688 const ReflectedEntry *ea = a;
5689 return mono_aligned_addr_hash (ea->item);
5692 #define CHECK_OBJECT(t,p,k) \
5698 mono_domain_lock (domain); \
5699 if (!domain->refobject_hash) \
5700 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5701 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5702 mono_domain_unlock (domain); \
5705 mono_domain_unlock (domain); \
5708 #ifdef HAVE_BOEHM_GC
5709 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5710 #define FREE_REFENTRY(entry) mono_gc_free_fixed ((entry))
5712 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5714 #define FREE_REFENTRY(entry)
5717 #define CACHE_OBJECT(t,p,o,k) \
5720 ReflectedEntry pe; \
5722 pe.refclass = (k); \
5723 mono_domain_lock (domain); \
5724 if (!domain->refobject_hash) \
5725 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5726 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5728 ReflectedEntry *e = ALLOC_REFENTRY; \
5730 e->refclass = (k); \
5731 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5734 mono_domain_unlock (domain); \
5739 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5741 mono_domain_lock (domain);
5742 if (domain->refobject_hash) {
5744 gpointer orig_pe, orig_value;
5747 pe.refclass = klass;
5748 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5749 mono_g_hash_table_remove (domain->refobject_hash, &pe);
5750 FREE_REFENTRY (orig_pe);
5753 mono_domain_unlock (domain);
5757 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5759 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5763 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5765 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5768 #ifndef DISABLE_REFLECTION_EMIT
5771 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5773 MonoDynamicImage *image = moduleb->dynamic_image;
5774 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5777 MonoImage **new_modules;
5780 * FIXME: we already created an image in mono_image_basic_init (), but
5781 * we don't know which module it belongs to, since that is only
5782 * determined at assembly save time.
5784 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5785 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5787 moduleb->module.image = &image->image;
5788 moduleb->dynamic_image = image;
5789 register_module (mono_object_domain (moduleb), moduleb, image);
5791 /* register the module with the assembly */
5792 ass = ab->dynamic_assembly->assembly.image;
5793 module_count = ass->module_count;
5794 new_modules = g_new0 (MonoImage *, module_count + 1);
5797 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5798 new_modules [module_count] = &image->image;
5799 mono_image_addref (&image->image);
5801 g_free (ass->modules);
5802 ass->modules = new_modules;
5803 ass->module_count ++;
5810 * mono_assembly_get_object:
5811 * @domain: an app domain
5812 * @assembly: an assembly
5814 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5816 MonoReflectionAssembly*
5817 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5819 static MonoClass *System_Reflection_Assembly;
5820 MonoReflectionAssembly *res;
5822 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5823 if (!System_Reflection_Assembly)
5824 System_Reflection_Assembly = mono_class_from_name (
5825 mono_defaults.corlib, "System.Reflection", "Assembly");
5826 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5827 res->assembly = assembly;
5829 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5834 MonoReflectionModule*
5835 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5837 static MonoClass *System_Reflection_Module;
5838 MonoReflectionModule *res;
5841 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5842 if (!System_Reflection_Module)
5843 System_Reflection_Module = mono_class_from_name (
5844 mono_defaults.corlib, "System.Reflection", "Module");
5845 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5848 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5850 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5851 basename = g_path_get_basename (image->name);
5852 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5853 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5857 if (image->assembly->image == image) {
5858 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5862 if (image->assembly->image->modules) {
5863 for (i = 0; i < image->assembly->image->module_count; i++) {
5864 if (image->assembly->image->modules [i] == image)
5865 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5867 g_assert (res->token);
5871 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5874 MonoReflectionModule*
5875 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5877 static MonoClass *System_Reflection_Module;
5878 MonoReflectionModule *res;
5879 MonoTableInfo *table;
5880 guint32 cols [MONO_FILE_SIZE];
5882 guint32 i, name_idx;
5885 if (!System_Reflection_Module)
5886 System_Reflection_Module = mono_class_from_name (
5887 mono_defaults.corlib, "System.Reflection", "Module");
5888 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5890 table = &image->tables [MONO_TABLE_FILE];
5891 g_assert (table_index < table->rows);
5892 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5895 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5896 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5898 /* Check whenever the row has a corresponding row in the moduleref table */
5899 table = &image->tables [MONO_TABLE_MODULEREF];
5900 for (i = 0; i < table->rows; ++i) {
5901 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5902 val = mono_metadata_string_heap (image, name_idx);
5903 if (strcmp (val, name) == 0)
5904 res->image = image->modules [i];
5907 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5908 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5909 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5910 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5911 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5917 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5919 if ((t1->type != t2->type) ||
5920 (t1->byref != t2->byref))
5924 case MONO_TYPE_VOID:
5925 case MONO_TYPE_BOOLEAN:
5926 case MONO_TYPE_CHAR:
5937 case MONO_TYPE_STRING:
5940 case MONO_TYPE_OBJECT:
5941 case MONO_TYPE_TYPEDBYREF:
5943 case MONO_TYPE_VALUETYPE:
5944 case MONO_TYPE_CLASS:
5945 case MONO_TYPE_SZARRAY:
5946 return t1->data.klass == t2->data.klass;
5948 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5949 case MONO_TYPE_ARRAY:
5950 if (t1->data.array->rank != t2->data.array->rank)
5952 return t1->data.array->eklass == t2->data.array->eklass;
5953 case MONO_TYPE_GENERICINST: {
5955 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5956 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5957 if (i1->type_argc != i2->type_argc)
5959 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5960 &t2->data.generic_class->container_class->byval_arg))
5962 /* FIXME: we should probably just compare the instance pointers directly. */
5963 for (i = 0; i < i1->type_argc; ++i) {
5964 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5970 case MONO_TYPE_MVAR:
5971 return t1->data.generic_param == t2->data.generic_param;
5973 g_error ("implement type compare for %0x!", t1->type);
5981 mymono_metadata_type_hash (MonoType *t1)
5987 hash |= t1->byref << 6; /* do not collide with t1->type values */
5989 case MONO_TYPE_VALUETYPE:
5990 case MONO_TYPE_CLASS:
5991 case MONO_TYPE_SZARRAY:
5992 /* check if the distribution is good enough */
5993 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5995 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5996 case MONO_TYPE_GENERICINST: {
5998 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5999 hash += g_str_hash (t1->data.generic_class->container_class->name);
6001 for (i = 0; i < inst->type_argc; ++i) {
6002 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6011 static MonoReflectionGenericClass*
6012 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6014 static MonoClass *System_Reflection_MonoGenericClass;
6015 MonoReflectionGenericClass *res;
6016 MonoClass *klass, *gklass;
6018 if (!System_Reflection_MonoGenericClass) {
6019 System_Reflection_MonoGenericClass = mono_class_from_name (
6020 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6021 g_assert (System_Reflection_MonoGenericClass);
6024 klass = mono_class_from_mono_type (geninst);
6025 gklass = klass->generic_class->container_class;
6027 mono_class_init (klass);
6030 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6032 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6035 res->type.type = geninst;
6036 g_assert (gklass->reflection_info);
6037 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6038 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6044 verify_safe_for_managed_space (MonoType *type)
6046 switch (type->type) {
6048 case MONO_TYPE_ARRAY:
6049 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6051 return verify_safe_for_managed_space (type->data.type);
6052 case MONO_TYPE_SZARRAY:
6053 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6054 case MONO_TYPE_GENERICINST: {
6055 MonoGenericInst *inst = type->data.generic_class->inst;
6059 for (i = 0; i < inst->type_argc; ++i)
6060 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6066 case MONO_TYPE_MVAR:
6073 * mono_type_get_object:
6074 * @domain: an app domain
6077 * Return an System.MonoType object representing the type @type.
6080 mono_type_get_object (MonoDomain *domain, MonoType *type)
6082 MonoReflectionType *res;
6083 MonoClass *klass = mono_class_from_mono_type (type);
6085 /*we must avoid using @type as it might have come
6086 * from a mono_metadata_type_dup and the caller
6087 * expects that is can be freed.
6088 * Using the right type from
6090 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6092 /* void is very common */
6093 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6094 return (MonoReflectionType*)domain->typeof_void;
6097 * If the vtable of the given class was already created, we can use
6098 * the MonoType from there and avoid all locking and hash table lookups.
6100 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6101 * that the resulting object is diferent.
6103 if (type == &klass->byval_arg && !klass->image->dynamic) {
6104 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6105 if (vtable && vtable->type)
6106 return vtable->type;
6109 mono_domain_lock (domain);
6110 if (!domain->type_hash)
6111 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6112 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6113 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6114 mono_domain_unlock (domain);
6117 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6118 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6119 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6120 mono_g_hash_table_insert (domain->type_hash, type, res);
6121 mono_domain_unlock (domain);
6125 if (!verify_safe_for_managed_space (type)) {
6126 mono_domain_unlock (domain);
6127 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6130 if (klass->reflection_info && !klass->wastypebuilder) {
6131 /* g_assert_not_reached (); */
6132 /* should this be considered an error condition? */
6134 mono_domain_unlock (domain);
6135 return klass->reflection_info;
6138 // FIXME: Get rid of this, do it in the icalls for Type
6139 mono_class_init (klass);
6141 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6143 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6146 mono_g_hash_table_insert (domain->type_hash, type, res);
6148 if (type->type == MONO_TYPE_VOID)
6149 MONO_OBJECT_SETREF (domain, typeof_void, res);
6151 mono_domain_unlock (domain);
6156 * mono_method_get_object:
6157 * @domain: an app domain
6159 * @refclass: the reflected type (can be NULL)
6161 * Return an System.Reflection.MonoMethod object representing the method @method.
6163 MonoReflectionMethod*
6164 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6167 * We use the same C representation for methods and constructors, but the type
6168 * name in C# is different.
6170 static MonoClass *System_Reflection_MonoMethod = NULL;
6171 static MonoClass *System_Reflection_MonoCMethod = NULL;
6172 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6173 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6175 MonoReflectionMethod *ret;
6178 * Don't let static RGCTX invoke wrappers get into
6179 * MonoReflectionMethods.
6181 if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
6182 method = mono_marshal_method_from_wrapper (method);
6184 if (method->is_inflated) {
6185 MonoReflectionGenericMethod *gret;
6187 refclass = method->klass;
6188 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6189 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6190 if (!System_Reflection_MonoGenericCMethod)
6191 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6192 klass = System_Reflection_MonoGenericCMethod;
6194 if (!System_Reflection_MonoGenericMethod)
6195 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6196 klass = System_Reflection_MonoGenericMethod;
6198 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6199 gret->method.method = method;
6200 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6201 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6202 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6206 refclass = method->klass;
6208 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6209 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6210 if (!System_Reflection_MonoCMethod)
6211 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6212 klass = System_Reflection_MonoCMethod;
6215 if (!System_Reflection_MonoMethod)
6216 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6217 klass = System_Reflection_MonoMethod;
6219 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6220 ret->method = method;
6221 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6222 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6226 * mono_method_clear_object:
6228 * Clear the cached reflection objects for the dynamic method METHOD.
6231 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6233 g_assert (method->dynamic);
6235 clear_cached_object (domain, method, method->klass);
6236 /* Added by mono_param_get_objects () */
6237 clear_cached_object (domain, &(method->signature), NULL);
6241 * mono_field_get_object:
6242 * @domain: an app domain
6246 * Return an System.Reflection.MonoField object representing the field @field
6249 MonoReflectionField*
6250 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6252 MonoReflectionField *res;
6253 static MonoClass *monofield_klass;
6255 CHECK_OBJECT (MonoReflectionField *, field, klass);
6256 if (!monofield_klass)
6257 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6258 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6261 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6262 if (is_field_on_inst (field))
6263 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6265 res->attrs = field->type->attrs;
6266 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6267 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6271 * mono_property_get_object:
6272 * @domain: an app domain
6274 * @property: a property
6276 * Return an System.Reflection.MonoProperty object representing the property @property
6279 MonoReflectionProperty*
6280 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6282 MonoReflectionProperty *res;
6283 static MonoClass *monoproperty_klass;
6285 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6286 if (!monoproperty_klass)
6287 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6288 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6290 res->property = property;
6291 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6295 * mono_event_get_object:
6296 * @domain: an app domain
6300 * Return an System.Reflection.MonoEvent object representing the event @event
6303 MonoReflectionEvent*
6304 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6306 MonoReflectionEvent *res;
6307 static MonoClass *monoevent_klass;
6309 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6310 if (!monoevent_klass)
6311 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6312 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6315 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6319 * mono_get_reflection_missing_object:
6320 * @domain: Domain where the object lives
6322 * Returns the System.Reflection.Missing.Value singleton object
6323 * (of type System.Reflection.Missing).
6325 * Used as the value for ParameterInfo.DefaultValue when Optional
6329 mono_get_reflection_missing_object (MonoDomain *domain)
6332 static MonoClassField *missing_value_field = NULL;
6334 if (!missing_value_field) {
6335 MonoClass *missing_klass;
6336 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6337 mono_class_init (missing_klass);
6338 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6339 g_assert (missing_value_field);
6341 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6347 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6350 *dbnull = mono_get_dbnull_object (domain);
6355 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6357 if (!*reflection_missing)
6358 *reflection_missing = mono_get_reflection_missing_object (domain);
6359 return *reflection_missing;
6363 * mono_param_get_objects:
6364 * @domain: an app domain
6367 * Return an System.Reflection.ParameterInfo array object representing the parameters
6368 * in the method @method.
6371 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6373 static MonoClass *System_Reflection_ParameterInfo;
6374 static MonoClass *System_Reflection_ParameterInfo_array;
6375 MonoArray *res = NULL;
6376 MonoReflectionMethod *member = NULL;
6377 MonoReflectionParameter *param = NULL;
6378 char **names, **blobs = NULL;
6379 guint32 *types = NULL;
6380 MonoType *type = NULL;
6381 MonoObject *dbnull = NULL;
6382 MonoObject *missing = NULL;
6383 MonoMarshalSpec **mspecs;
6384 MonoMethodSignature *sig;
6385 MonoVTable *pinfo_vtable;
6388 if (!System_Reflection_ParameterInfo_array) {
6391 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6392 mono_memory_barrier ();
6393 System_Reflection_ParameterInfo = klass;
6395 klass = mono_array_class_get (klass, 1);
6396 mono_memory_barrier ();
6397 System_Reflection_ParameterInfo_array = klass;
6400 if (!mono_method_signature (method)->param_count)
6401 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6403 /* Note: the cache is based on the address of the signature into the method
6404 * since we already cache MethodInfos with the method as keys.
6406 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6408 sig = mono_method_signature (method);
6409 member = mono_method_get_object (domain, method, NULL);
6410 names = g_new (char *, sig->param_count);
6411 mono_method_get_param_names (method, (const char **) names);
6413 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6414 mono_method_get_marshal_info (method, mspecs);
6416 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6417 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6418 for (i = 0; i < sig->param_count; ++i) {
6419 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6420 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6421 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6422 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6423 param->PositionImpl = i;
6424 param->AttrsImpl = sig->params [i]->attrs;
6426 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6427 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6428 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6430 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6434 blobs = g_new0 (char *, sig->param_count);
6435 types = g_new0 (guint32, sig->param_count);
6436 get_default_param_value_blobs (method, blobs, types);
6439 /* Build MonoType for the type from the Constant Table */
6441 type = g_new0 (MonoType, 1);
6442 type->type = types [i];
6443 type->data.klass = NULL;
6444 if (types [i] == MONO_TYPE_CLASS)
6445 type->data.klass = mono_defaults.object_class;
6446 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6447 /* For enums, types [i] contains the base type */
6449 type->type = MONO_TYPE_VALUETYPE;
6450 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6452 type->data.klass = mono_class_from_mono_type (type);
6454 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6456 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6457 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6458 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6459 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6461 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6467 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6469 mono_array_setref (res, i, param);
6476 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6478 mono_metadata_free_marshal_spec (mspecs [i]);
6481 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6485 * mono_method_body_get_object:
6486 * @domain: an app domain
6489 * Return an System.Reflection.MethodBody object representing the method @method.
6491 MonoReflectionMethodBody*
6492 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6494 static MonoClass *System_Reflection_MethodBody = NULL;
6495 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6496 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6497 MonoReflectionMethodBody *ret;
6498 MonoMethodNormal *mn;
6499 MonoMethodHeader *header;
6500 guint32 method_rva, local_var_sig_token;
6502 unsigned char format, flags;
6505 if (!System_Reflection_MethodBody)
6506 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6507 if (!System_Reflection_LocalVariableInfo)
6508 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6509 if (!System_Reflection_ExceptionHandlingClause)
6510 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6512 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6514 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6515 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6516 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6517 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6519 mn = (MonoMethodNormal *)method;
6520 header = mono_method_get_header (method);
6522 /* Obtain local vars signature token */
6523 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6524 ptr = mono_image_rva_map (method->klass->image, method_rva);
6525 flags = *(const unsigned char *) ptr;
6526 format = flags & METHOD_HEADER_FORMAT_MASK;
6528 case METHOD_HEADER_TINY_FORMAT:
6529 case METHOD_HEADER_TINY_FORMAT1:
6530 local_var_sig_token = 0;
6532 case METHOD_HEADER_FAT_FORMAT:
6536 local_var_sig_token = read32 (ptr);
6539 g_assert_not_reached ();
6542 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6544 ret->init_locals = header->init_locals;
6545 ret->max_stack = header->max_stack;
6546 ret->local_var_sig_token = local_var_sig_token;
6547 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6548 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6551 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6552 for (i = 0; i < header->num_locals; ++i) {
6553 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6554 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6555 info->is_pinned = header->locals [i]->pinned;
6556 info->local_index = i;
6557 mono_array_setref (ret->locals, i, info);
6561 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6562 for (i = 0; i < header->num_clauses; ++i) {
6563 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6564 MonoExceptionClause *clause = &header->clauses [i];
6566 info->flags = clause->flags;
6567 info->try_offset = clause->try_offset;
6568 info->try_length = clause->try_len;
6569 info->handler_offset = clause->handler_offset;
6570 info->handler_length = clause->handler_len;
6571 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6572 info->filter_offset = clause->data.filter_offset;
6573 else if (clause->data.catch_class)
6574 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6576 mono_array_setref (ret->clauses, i, info);
6579 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6584 * mono_get_dbnull_object:
6585 * @domain: Domain where the object lives
6587 * Returns the System.DBNull.Value singleton object
6589 * Used as the value for ParameterInfo.DefaultValue
6592 mono_get_dbnull_object (MonoDomain *domain)
6595 static MonoClassField *dbnull_value_field = NULL;
6597 if (!dbnull_value_field) {
6598 MonoClass *dbnull_klass;
6599 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6600 mono_class_init (dbnull_klass);
6601 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6602 g_assert (dbnull_value_field);
6604 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6610 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6612 guint32 param_index, i, lastp, crow = 0;
6613 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6616 MonoClass *klass = method->klass;
6617 MonoImage *image = klass->image;
6618 MonoMethodSignature *methodsig = mono_method_signature (method);
6620 MonoTableInfo *constt;
6621 MonoTableInfo *methodt;
6622 MonoTableInfo *paramt;
6624 if (!methodsig->param_count)
6627 mono_class_init (klass);
6629 if (klass->image->dynamic) {
6630 MonoReflectionMethodAux *aux;
6631 if (method->is_inflated)
6632 method = ((MonoMethodInflated*)method)->declaring;
6633 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6634 if (aux && aux->param_defaults) {
6635 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6636 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6641 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6642 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6643 constt = &image->tables [MONO_TABLE_CONSTANT];
6645 idx = mono_method_get_index (method) - 1;
6646 g_assert (idx != -1);
6648 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6649 if (idx + 1 < methodt->rows)
6650 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6652 lastp = paramt->rows + 1;
6654 for (i = param_index; i < lastp; ++i) {
6657 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6658 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6660 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6663 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6668 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6669 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6670 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6677 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6682 MonoType *basetype = type;
6687 klass = mono_class_from_mono_type (type);
6688 if (klass->valuetype) {
6689 object = mono_object_new (domain, klass);
6690 retval = ((gchar *) object + sizeof (MonoObject));
6691 if (klass->enumtype)
6692 basetype = mono_class_enum_basetype (klass);
6697 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6704 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6708 memset (assembly, 0, sizeof (MonoAssemblyName));
6710 assembly->culture = "";
6711 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6713 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6716 while (g_ascii_isspace (*p) || *p == ',') {
6725 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6727 assembly->major = strtoul (p, &s, 10);
6728 if (s == p || *s != '.')
6731 assembly->minor = strtoul (p, &s, 10);
6732 if (s == p || *s != '.')
6735 assembly->build = strtoul (p, &s, 10);
6736 if (s == p || *s != '.')
6739 assembly->revision = strtoul (p, &s, 10);
6743 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6745 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6746 assembly->culture = "";
6749 assembly->culture = p;
6750 while (*p && *p != ',') {
6754 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6756 if (strncmp (p, "null", 4) == 0) {
6761 while (*p && *p != ',') {
6764 len = (p - start + 1);
6765 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6766 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6767 g_strlcpy ((char*)assembly->public_key_token, start, len);
6770 while (*p && *p != ',')
6774 while (g_ascii_isspace (*p) || *p == ',') {
6788 * mono_reflection_parse_type:
6791 * Parse a type name as accepted by the GetType () method and output the info
6792 * extracted in the info structure.
6793 * the name param will be mangled, so, make a copy before passing it to this function.
6794 * The fields in info will be valid until the memory pointed to by name is valid.
6796 * See also mono_type_get_name () below.
6798 * Returns: 0 on parse error.
6801 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6802 MonoTypeNameParse *info)
6804 char *start, *p, *w, *temp, *last_point, *startn;
6805 int in_modifiers = 0;
6806 int isbyref = 0, rank, arity = 0, i;
6808 start = p = w = name;
6810 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6811 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6812 info->name = info->name_space = NULL;
6813 info->nested = NULL;
6814 info->modifiers = NULL;
6815 info->type_arguments = NULL;
6817 /* last_point separates the namespace from the name */
6820 while (*p == ' ') p++, start++, w++, name++;
6825 *p = 0; /* NULL terminate the name */
6827 info->nested = g_list_append (info->nested, startn);
6828 /* we have parsed the nesting namespace + name */
6832 info->name_space = start;
6834 info->name = last_point + 1;
6836 info->name_space = (char *)"";
6855 i = strtol (p, &temp, 10);
6872 info->name_space = start;
6874 info->name = last_point + 1;
6876 info->name_space = (char *)"";
6883 if (isbyref) /* only one level allowed by the spec */
6886 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6890 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6896 info->type_arguments = g_ptr_array_new ();
6897 for (i = 0; i < arity; i++) {
6898 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6899 gboolean fqname = FALSE;
6901 g_ptr_array_add (info->type_arguments, subinfo);
6908 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6919 while (*p && (*p != ']'))
6927 if (g_ascii_isspace (*aname)) {
6934 !assembly_name_to_aname (&subinfo->assembly, aname))
6938 if (i + 1 < arity) {
6958 else if (*p == '*') /* '*' means unknown lower bound */
6959 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6966 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6977 if (g_ascii_isspace (*p)) {
6984 return 0; /* missing assembly name */
6985 if (!assembly_name_to_aname (&info->assembly, p))
6991 if (info->assembly.name)
6994 // *w = 0; /* terminate class name */
6996 if (!info->name || !*info->name)
7000 /* add other consistency checks */
7005 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7007 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7011 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7013 gboolean type_resolve = FALSE;
7015 MonoImage *rootimage = image;
7017 if (info->assembly.name) {
7018 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7019 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7021 * This could happen in the AOT compiler case when the search hook is not
7024 assembly = image->assembly;
7026 /* then we must load the assembly ourselve - see #60439 */
7027 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7031 image = assembly->image;
7032 } else if (!image) {
7033 image = mono_defaults.corlib;
7036 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7037 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7038 image = mono_defaults.corlib;
7039 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7046 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7051 gboolean bounded = FALSE;
7054 image = mono_defaults.corlib;
7057 klass = mono_class_from_name_case (image, info->name_space, info->name);
7059 klass = mono_class_from_name (image, info->name_space, info->name);
7062 for (mod = info->nested; mod; mod = mod->next) {
7063 gpointer iter = NULL;
7067 mono_class_init (parent);
7069 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7071 if (g_strcasecmp (klass->name, mod->data) == 0)
7074 if (strcmp (klass->name, mod->data) == 0)
7083 mono_class_init (klass);
7085 if (info->type_arguments) {
7086 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7087 MonoReflectionType *the_type;
7091 for (i = 0; i < info->type_arguments->len; i++) {
7092 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7094 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7095 if (!type_args [i]) {
7101 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7103 instance = mono_reflection_bind_generic_parameters (
7104 the_type, info->type_arguments->len, type_args);
7110 klass = mono_class_from_mono_type (instance);
7113 for (mod = info->modifiers; mod; mod = mod->next) {
7114 modval = GPOINTER_TO_UINT (mod->data);
7115 if (!modval) { /* byref: must be last modifier */
7116 return &klass->this_arg;
7117 } else if (modval == -1) {
7118 klass = mono_ptr_class_get (&klass->byval_arg);
7119 } else if (modval == -2) {
7121 } else { /* array rank */
7122 klass = mono_bounded_array_class_get (klass, modval, bounded);
7124 mono_class_init (klass);
7127 return &klass->byval_arg;
7131 * mono_reflection_get_type:
7132 * @image: a metadata context
7133 * @info: type description structure
7134 * @ignorecase: flag for case-insensitive string compares
7135 * @type_resolve: whenever type resolve was already tried
7137 * Build a MonoType from the type description in @info.
7142 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7143 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7147 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7149 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7153 g_assert (assembly->dynamic);
7155 /* Enumerate all modules */
7158 if (abuilder->modules) {
7159 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7160 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7161 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7167 if (!type && abuilder->loaded_modules) {
7168 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7169 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7170 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7180 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7183 MonoReflectionAssembly *assembly;
7187 if (image && image->dynamic)
7188 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7190 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7193 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7200 *type_resolve = TRUE;
7203 /* Reconstruct the type name */
7204 fullName = g_string_new ("");
7205 if (info->name_space && (info->name_space [0] != '\0'))
7206 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7208 g_string_printf (fullName, info->name);
7209 for (mod = info->nested; mod; mod = mod->next)
7210 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7212 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7214 if (assembly->assembly->dynamic)
7215 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7217 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7220 g_string_free (fullName, TRUE);
7225 mono_reflection_free_type_info (MonoTypeNameParse *info)
7227 g_list_free (info->modifiers);
7228 g_list_free (info->nested);
7230 if (info->type_arguments) {
7233 for (i = 0; i < info->type_arguments->len; i++) {
7234 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7236 mono_reflection_free_type_info (subinfo);
7237 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7241 g_ptr_array_free (info->type_arguments, TRUE);
7246 * mono_reflection_type_from_name:
7248 * @image: a metadata context (can be NULL).
7250 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7251 * it defaults to get the type from @image or, if @image is NULL or loading
7252 * from it fails, uses corlib.
7256 mono_reflection_type_from_name (char *name, MonoImage *image)
7258 MonoType *type = NULL;
7259 MonoTypeNameParse info;
7262 /* Make a copy since parse_type modifies its argument */
7263 tmp = g_strdup (name);
7265 /*g_print ("requested type %s\n", str);*/
7266 if (mono_reflection_parse_type (tmp, &info)) {
7267 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7271 mono_reflection_free_type_info (&info);
7276 * mono_reflection_get_token:
7278 * Return the metadata token of OBJ which should be an object
7279 * representing a metadata element.
7282 mono_reflection_get_token (MonoObject *obj)
7287 klass = obj->vtable->klass;
7289 if (strcmp (klass->name, "MethodBuilder") == 0) {
7290 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7292 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7293 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7294 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7296 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7297 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7298 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7300 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7301 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7302 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7303 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7304 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7305 } else if (strcmp (klass->name, "MonoType") == 0) {
7306 MonoReflectionType *tb = (MonoReflectionType *)obj;
7307 token = mono_class_from_mono_type (tb->type)->type_token;
7308 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7309 strcmp (klass->name, "MonoMethod") == 0 ||
7310 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7311 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7312 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7313 if (m->method->is_inflated) {
7314 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7315 return inflated->declaring->token;
7317 token = m->method->token;
7319 } else if (strcmp (klass->name, "MonoField") == 0) {
7320 MonoReflectionField *f = (MonoReflectionField*)obj;
7322 if (is_field_on_inst (f->field)) {
7323 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7324 int field_index = f->field - dgclass->fields;
7327 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7328 obj = dgclass->field_objects [field_index];
7329 return mono_reflection_get_token (obj);
7331 token = mono_class_get_field_token (f->field);
7332 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7333 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7335 token = mono_class_get_property_token (p->property);
7336 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7337 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7339 token = mono_class_get_event_token (p->event);
7340 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7341 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7343 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7344 } else if (strcmp (klass->name, "Module") == 0) {
7345 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7348 } else if (strcmp (klass->name, "Assembly") == 0) {
7349 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7351 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7352 MonoException *ex = mono_get_exception_not_implemented (msg);
7354 mono_raise_exception (ex);
7361 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7363 int slen, type = t->type;
7364 MonoClass *tklass = t->data.klass;
7370 case MONO_TYPE_BOOLEAN: {
7371 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7376 case MONO_TYPE_CHAR:
7378 case MONO_TYPE_I2: {
7379 guint16 *val = g_malloc (sizeof (guint16));
7384 #if SIZEOF_VOID_P == 4
7390 case MONO_TYPE_I4: {
7391 guint32 *val = g_malloc (sizeof (guint32));
7396 #if SIZEOF_VOID_P == 8
7397 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7401 case MONO_TYPE_I8: {
7402 guint64 *val = g_malloc (sizeof (guint64));
7407 case MONO_TYPE_R8: {
7408 double *val = g_malloc (sizeof (double));
7413 case MONO_TYPE_VALUETYPE:
7414 if (t->data.klass->enumtype) {
7415 type = mono_class_enum_basetype (t->data.klass)->type;
7418 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7421 case MONO_TYPE_STRING:
7422 if (*p == (char)0xFF) {
7426 slen = mono_metadata_decode_value (p, &p);
7428 return mono_string_new_len (mono_domain_get (), p, slen);
7429 case MONO_TYPE_CLASS: {
7432 if (*p == (char)0xFF) {
7437 slen = mono_metadata_decode_value (p, &p);
7438 n = g_memdup (p, slen + 1);
7440 t = mono_reflection_type_from_name (n, image);
7442 g_warning ("Cannot load type '%s'", n);
7446 return mono_type_get_object (mono_domain_get (), t);
7450 case MONO_TYPE_OBJECT: {
7453 MonoClass *subc = NULL;
7458 } else if (subt == 0x0E) {
7459 type = MONO_TYPE_STRING;
7461 } else if (subt == 0x1D) {
7462 MonoType simple_type = {{0}};
7467 /* See Partition II, Appendix B3 */
7468 etype = MONO_TYPE_OBJECT;
7469 type = MONO_TYPE_SZARRAY;
7470 simple_type.type = etype;
7471 tklass = mono_class_from_mono_type (&simple_type);
7473 } else if (subt == 0x55) {
7476 slen = mono_metadata_decode_value (p, &p);
7477 n = g_memdup (p, slen + 1);
7479 t = mono_reflection_type_from_name (n, image);
7481 g_error ("Cannot load type '%s'", n);
7484 subc = mono_class_from_mono_type (t);
7485 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7486 MonoType simple_type = {{0}};
7487 simple_type.type = subt;
7488 subc = mono_class_from_mono_type (&simple_type);
7490 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7492 val = load_cattr_value (image, &subc->byval_arg, p, end);
7493 obj = mono_object_new (mono_domain_get (), subc);
7494 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7498 case MONO_TYPE_SZARRAY: {
7500 guint32 i, alen, basetype;
7503 if (alen == 0xffffffff) {
7507 arr = mono_array_new (mono_domain_get(), tklass, alen);
7508 basetype = tklass->byval_arg.type;
7509 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7510 basetype = mono_class_enum_basetype (tklass)->type;
7515 case MONO_TYPE_BOOLEAN:
7516 for (i = 0; i < alen; i++) {
7517 MonoBoolean val = *p++;
7518 mono_array_set (arr, MonoBoolean, i, val);
7521 case MONO_TYPE_CHAR:
7524 for (i = 0; i < alen; i++) {
7525 guint16 val = read16 (p);
7526 mono_array_set (arr, guint16, i, val);
7533 for (i = 0; i < alen; i++) {
7534 guint32 val = read32 (p);
7535 mono_array_set (arr, guint32, i, val);
7540 for (i = 0; i < alen; i++) {
7543 mono_array_set (arr, double, i, val);
7549 for (i = 0; i < alen; i++) {
7550 guint64 val = read64 (p);
7551 mono_array_set (arr, guint64, i, val);
7555 case MONO_TYPE_CLASS:
7556 case MONO_TYPE_OBJECT:
7557 case MONO_TYPE_STRING:
7558 for (i = 0; i < alen; i++) {
7559 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7560 mono_array_setref (arr, i, item);
7564 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7570 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7576 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7578 static MonoClass *klass;
7579 static MonoMethod *ctor;
7581 void *params [2], *unboxed;
7584 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7586 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7588 params [0] = mono_type_get_object (mono_domain_get (), t);
7590 retval = mono_object_new (mono_domain_get (), klass);
7591 unboxed = mono_object_unbox (retval);
7592 mono_runtime_invoke (ctor, unboxed, params, NULL);
7598 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7600 static MonoClass *klass;
7601 static MonoMethod *ctor;
7603 void *unboxed, *params [2];
7606 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7608 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7611 params [1] = typedarg;
7612 retval = mono_object_new (mono_domain_get (), klass);
7613 unboxed = mono_object_unbox (retval);
7614 mono_runtime_invoke (ctor, unboxed, params, NULL);
7620 type_is_reference (MonoType *type)
7622 switch (type->type) {
7623 case MONO_TYPE_BOOLEAN:
7624 case MONO_TYPE_CHAR:
7637 case MONO_TYPE_VALUETYPE:
7645 free_param_data (MonoMethodSignature *sig, void **params) {
7647 for (i = 0; i < sig->param_count; ++i) {
7648 if (!type_is_reference (sig->params [i]))
7649 g_free (params [i]);
7654 * Find the field index in the metadata FieldDef table.
7657 find_field_index (MonoClass *klass, MonoClassField *field) {
7660 for (i = 0; i < klass->field.count; ++i) {
7661 if (field == &klass->fields [i])
7662 return klass->field.first + 1 + i;
7668 * Find the property index in the metadata Property table.
7671 find_property_index (MonoClass *klass, MonoProperty *property) {
7674 for (i = 0; i < klass->ext->property.count; ++i) {
7675 if (property == &klass->ext->properties [i])
7676 return klass->ext->property.first + 1 + i;
7682 * Find the event index in the metadata Event table.
7685 find_event_index (MonoClass *klass, MonoEvent *event) {
7688 for (i = 0; i < klass->ext->event.count; ++i) {
7689 if (event == &klass->ext->events [i])
7690 return klass->ext->event.first + 1 + i;
7696 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7698 const char *p = (const char*)data;
7700 guint32 i, j, num_named;
7702 void *params_buf [32];
7704 MonoMethodSignature *sig;
7706 mono_class_init (method->klass);
7709 attr = mono_object_new (mono_domain_get (), method->klass);
7710 mono_runtime_invoke (method, attr, NULL, NULL);
7714 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7717 /*g_print ("got attr %s\n", method->klass->name);*/
7719 sig = mono_method_signature (method);
7720 if (sig->param_count < 32)
7721 params = params_buf;
7723 /* Allocate using GC so it gets GC tracking */
7724 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
7728 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7729 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7733 attr = mono_object_new (mono_domain_get (), method->klass);
7734 mono_runtime_invoke (method, attr, params, NULL);
7735 free_param_data (method->signature, params);
7736 num_named = read16 (named);
7738 for (j = 0; j < num_named; j++) {
7740 char *name, named_type, data_type;
7741 named_type = *named++;
7742 data_type = *named++; /* type of data */
7743 if (data_type == MONO_TYPE_SZARRAY)
7744 data_type = *named++;
7745 if (data_type == MONO_TYPE_ENUM) {
7748 type_len = mono_metadata_decode_blob_size (named, &named);
7749 type_name = g_malloc (type_len + 1);
7750 memcpy (type_name, named, type_len);
7751 type_name [type_len] = 0;
7753 /* FIXME: lookup the type and check type consistency */
7756 name_len = mono_metadata_decode_blob_size (named, &named);
7757 name = g_malloc (name_len + 1);
7758 memcpy (name, named, name_len);
7759 name [name_len] = 0;
7761 if (named_type == 0x53) {
7762 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7763 void *val = load_cattr_value (image, field->type, named, &named);
7764 mono_field_set_value (attr, field, val);
7765 if (!type_is_reference (field->type))
7767 } else if (named_type == 0x54) {
7770 MonoType *prop_type;
7772 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7773 /* can we have more that 1 arg in a custom attr named property? */
7774 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7775 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7776 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7777 mono_property_set_value (prop, attr, pparams, NULL);
7778 if (!type_is_reference (prop_type))
7779 g_free (pparams [0]);
7784 if (params != params_buf)
7785 mono_gc_free_fixed (params);
7791 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7793 MonoArray *typedargs, *namedargs;
7794 MonoClass *attrklass;
7795 static MonoMethod *ctor;
7798 const char *p = (const char*)data;
7800 guint32 i, j, num_named;
7803 mono_class_init (method->klass);
7806 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7808 domain = mono_domain_get ();
7810 /* This is for Attributes with no parameters */
7811 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7812 params [0] = mono_method_get_object (domain, method, NULL);
7813 params [1] = params [2] = NULL;
7814 mono_runtime_invoke (method, attr, params, NULL);
7818 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7821 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7825 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7826 MonoObject *obj, *typedarg;
7829 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7830 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7831 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7832 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7833 mono_array_setref (typedargs, i, typedarg);
7835 if (!type_is_reference (mono_method_signature (method)->params [i]))
7840 num_named = read16 (named);
7841 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7843 attrklass = method->klass;
7844 for (j = 0; j < num_named; j++) {
7846 char *name, named_type, data_type;
7847 named_type = *named++;
7848 data_type = *named++; /* type of data */
7849 if (data_type == MONO_TYPE_SZARRAY)
7850 data_type = *named++;
7851 if (data_type == MONO_TYPE_ENUM) {
7854 type_len = mono_metadata_decode_blob_size (named, &named);
7855 type_name = g_malloc (type_len + 1);
7856 memcpy (type_name, named, type_len);
7857 type_name [type_len] = 0;
7859 /* FIXME: lookup the type and check type consistency */
7862 name_len = mono_metadata_decode_blob_size (named, &named);
7863 name = g_malloc (name_len + 1);
7864 memcpy (name, named, name_len);
7865 name [name_len] = 0;
7867 if (named_type == 0x53) {
7868 MonoObject *obj, *typedarg, *namedarg;
7869 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7870 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7872 minfo = mono_field_get_object (domain, NULL, field);
7873 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7874 typedarg = create_cattr_typed_arg (field->type, obj);
7875 namedarg = create_cattr_named_arg (minfo, typedarg);
7876 mono_array_setref (namedargs, j, namedarg);
7877 if (!type_is_reference (field->type))
7879 } else if (named_type == 0x54) {
7880 MonoObject *obj, *typedarg, *namedarg;
7881 MonoType *prop_type;
7883 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7885 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7886 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7887 minfo = mono_property_get_object (domain, NULL, prop);
7888 val = load_cattr_value (image, prop_type, named, &named);
7889 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7890 typedarg = create_cattr_typed_arg (prop_type, obj);
7891 namedarg = create_cattr_named_arg (minfo, typedarg);
7892 mono_array_setref (namedargs, j, namedarg);
7893 if (!type_is_reference (prop_type))
7898 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7899 params [0] = mono_method_get_object (domain, method, NULL);
7900 params [1] = typedargs;
7901 params [2] = namedargs;
7902 mono_runtime_invoke (ctor, attr, params, NULL);
7907 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7913 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7914 for (i = 0; i < cinfo->num_attrs; ++i) {
7915 if (!cinfo->attrs [i].ctor)
7916 /* The cattr type is not finished yet */
7917 /* We should include the type name but cinfo doesn't contain it */
7918 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7919 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7920 mono_array_setref (result, i, attr);
7926 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7933 for (i = 0; i < cinfo->num_attrs; ++i) {
7934 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7938 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7940 for (i = 0; i < cinfo->num_attrs; ++i) {
7941 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7942 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7943 mono_array_setref (result, n, attr);
7951 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7957 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7958 for (i = 0; i < cinfo->num_attrs; ++i) {
7959 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7960 mono_array_setref (result, i, attr);
7966 * mono_custom_attrs_from_index:
7968 * Returns: NULL if no attributes are found or if a loading error occurs.
7971 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7973 guint32 mtoken, i, len;
7974 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7976 MonoCustomAttrInfo *ainfo;
7977 GList *tmp, *list = NULL;
7980 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7982 i = mono_metadata_custom_attrs_from_index (image, idx);
7986 while (i < ca->rows) {
7987 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7989 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7992 len = g_list_length (list);
7995 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7996 ainfo->num_attrs = len;
7997 ainfo->image = image;
7998 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7999 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8000 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8001 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8002 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8003 mtoken |= MONO_TOKEN_METHOD_DEF;
8005 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8006 mtoken |= MONO_TOKEN_MEMBER_REF;
8009 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8012 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8013 if (!ainfo->attrs [i].ctor) {
8014 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8019 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8020 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8021 ainfo->attrs [i].data = (guchar*)data;
8029 mono_custom_attrs_from_method (MonoMethod *method)
8034 * An instantiated method has the same cattrs as the generic method definition.
8036 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8037 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8039 if (method->is_inflated)
8040 method = ((MonoMethodInflated *) method)->declaring;
8042 if (method->dynamic || method->klass->image->dynamic)
8043 return lookup_custom_attr (method->klass->image, method);
8045 idx = mono_method_get_index (method);
8046 idx <<= MONO_CUSTOM_ATTR_BITS;
8047 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8048 return mono_custom_attrs_from_index (method->klass->image, idx);
8052 mono_custom_attrs_from_class (MonoClass *klass)
8056 if (klass->generic_class)
8057 klass = klass->generic_class->container_class;
8059 if (klass->image->dynamic)
8060 return lookup_custom_attr (klass->image, klass);
8062 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8063 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8064 idx <<= MONO_CUSTOM_ATTR_BITS;
8065 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8067 idx = mono_metadata_token_index (klass->type_token);
8068 idx <<= MONO_CUSTOM_ATTR_BITS;
8069 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8071 return mono_custom_attrs_from_index (klass->image, idx);
8075 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8079 if (assembly->image->dynamic)
8080 return lookup_custom_attr (assembly->image, assembly);
8081 idx = 1; /* there is only one assembly */
8082 idx <<= MONO_CUSTOM_ATTR_BITS;
8083 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8084 return mono_custom_attrs_from_index (assembly->image, idx);
8087 static MonoCustomAttrInfo*
8088 mono_custom_attrs_from_module (MonoImage *image)
8093 return lookup_custom_attr (image, image);
8094 idx = 1; /* there is only one module */
8095 idx <<= MONO_CUSTOM_ATTR_BITS;
8096 idx |= MONO_CUSTOM_ATTR_MODULE;
8097 return mono_custom_attrs_from_index (image, idx);
8101 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8105 if (klass->image->dynamic) {
8106 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8107 return lookup_custom_attr (klass->image, property);
8109 idx = find_property_index (klass, property);
8110 idx <<= MONO_CUSTOM_ATTR_BITS;
8111 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8112 return mono_custom_attrs_from_index (klass->image, idx);
8116 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8120 if (klass->image->dynamic) {
8121 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8122 return lookup_custom_attr (klass->image, event);
8124 idx = find_event_index (klass, event);
8125 idx <<= MONO_CUSTOM_ATTR_BITS;
8126 idx |= MONO_CUSTOM_ATTR_EVENT;
8127 return mono_custom_attrs_from_index (klass->image, idx);
8131 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8134 if (klass->image->dynamic) {
8135 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8136 return lookup_custom_attr (klass->image, field);
8138 idx = find_field_index (klass, field);
8139 idx <<= MONO_CUSTOM_ATTR_BITS;
8140 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8141 return mono_custom_attrs_from_index (klass->image, idx);
8145 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8148 guint32 i, idx, method_index;
8149 guint32 param_list, param_last, param_pos, found;
8151 MonoReflectionMethodAux *aux;
8154 * An instantiated method has the same cattrs as the generic method definition.
8156 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8157 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8159 if (method->is_inflated)
8160 method = ((MonoMethodInflated *) method)->declaring;
8162 if (method->klass->image->dynamic) {
8163 MonoCustomAttrInfo *res, *ainfo;
8166 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8167 if (!aux || !aux->param_cattr)
8170 /* Need to copy since it will be freed later */
8171 ainfo = aux->param_cattr [param];
8172 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
8173 res = g_malloc0 (size);
8174 memcpy (res, ainfo, size);
8178 image = method->klass->image;
8179 method_index = mono_method_get_index (method);
8180 ca = &image->tables [MONO_TABLE_METHOD];
8182 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8183 if (method_index == ca->rows) {
8184 ca = &image->tables [MONO_TABLE_PARAM];
8185 param_last = ca->rows + 1;
8187 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8188 ca = &image->tables [MONO_TABLE_PARAM];
8191 for (i = param_list; i < param_last; ++i) {
8192 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8193 if (param_pos == param) {
8201 idx <<= MONO_CUSTOM_ATTR_BITS;
8202 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8203 return mono_custom_attrs_from_index (image, idx);
8207 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8211 for (i = 0; i < ainfo->num_attrs; ++i) {
8212 klass = ainfo->attrs [i].ctor->klass;
8213 if (mono_class_has_parent (klass, attr_klass))
8220 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8227 for (i = 0; i < ainfo->num_attrs; ++i) {
8228 klass = ainfo->attrs [i].ctor->klass;
8229 if (mono_class_has_parent (klass, attr_klass)) {
8234 if (attr_index == -1)
8237 attrs = mono_custom_attrs_construct (ainfo);
8239 return mono_array_get (attrs, MonoObject*, attr_index);
8245 * mono_reflection_get_custom_attrs_info:
8246 * @obj: a reflection object handle
8248 * Return the custom attribute info for attributes defined for the
8249 * reflection handle @obj. The objects.
8251 * FIXME this function leaks like a sieve for SRE objects.
8254 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8257 MonoCustomAttrInfo *cinfo = NULL;
8259 klass = obj->vtable->klass;
8260 if (klass == mono_defaults.monotype_class) {
8261 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8262 klass = mono_class_from_mono_type (rtype->type);
8263 cinfo = mono_custom_attrs_from_class (klass);
8264 } else if (strcmp ("Assembly", klass->name) == 0) {
8265 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8266 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8267 } else if (strcmp ("Module", klass->name) == 0) {
8268 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8269 cinfo = mono_custom_attrs_from_module (module->image);
8270 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8271 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8272 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8273 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8274 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
8275 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8276 } else if (strcmp ("MonoField", klass->name) == 0) {
8277 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8278 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8279 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8280 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8281 cinfo = mono_custom_attrs_from_method (rmethod->method);
8282 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8283 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8284 cinfo = mono_custom_attrs_from_method (rmethod->method);
8285 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8286 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8287 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8288 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8289 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8290 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8291 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8292 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8293 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8294 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8295 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8296 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8297 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8298 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8299 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8300 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8301 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8302 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8303 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8304 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8305 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8306 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8307 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8308 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8309 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8310 } else { /* handle other types here... */
8311 g_error ("get custom attrs not yet supported for %s", klass->name);
8318 * mono_reflection_get_custom_attrs_by_type:
8319 * @obj: a reflection object handle
8321 * Return an array with all the custom attributes defined of the
8322 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8323 * of that type are returned. The objects are fully build. Return NULL if a loading error
8327 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8330 MonoCustomAttrInfo *cinfo;
8332 cinfo = mono_reflection_get_custom_attrs_info (obj);
8335 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8337 result = mono_custom_attrs_construct (cinfo);
8339 mono_custom_attrs_free (cinfo);
8341 if (mono_loader_get_last_error ())
8343 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8350 * mono_reflection_get_custom_attrs:
8351 * @obj: a reflection object handle
8353 * Return an array with all the custom attributes defined of the
8354 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8358 mono_reflection_get_custom_attrs (MonoObject *obj)
8360 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8364 * mono_reflection_get_custom_attrs_data:
8365 * @obj: a reflection obj handle
8367 * Returns an array of System.Reflection.CustomAttributeData,
8368 * which include information about attributes reflected on
8369 * types loaded using the Reflection Only methods
8372 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8375 MonoCustomAttrInfo *cinfo;
8377 cinfo = mono_reflection_get_custom_attrs_info (obj);
8379 result = mono_custom_attrs_data_construct (cinfo);
8381 mono_custom_attrs_free (cinfo);
8383 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8388 static MonoReflectionType*
8389 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8391 MonoMethod *method_get_underlying_system_type;
8393 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8394 mono_class_get_method_from_name (mono_object_class (t),
8395 "get_UnderlyingSystemType",
8397 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8401 mono_reflection_type_get_handle (MonoReflectionType* t)
8406 t = mono_reflection_type_get_underlying_system_type (t);
8414 * LOCKING: Assumes the loader lock is held.
8416 static MonoMethodSignature*
8417 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8418 MonoMethodSignature *sig;
8421 count = parameters? mono_array_length (parameters): 0;
8423 sig = image_g_malloc0 (image, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8424 sig->param_count = count;
8425 sig->sentinelpos = -1; /* FIXME */
8426 for (i = 0; i < count; ++i) {
8427 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8428 sig->params [i] = mono_reflection_type_get_handle (pt);
8434 * LOCKING: Assumes the loader lock is held.
8436 static MonoMethodSignature*
8437 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8438 MonoMethodSignature *sig;
8440 sig = parameters_to_signature (image, ctor->parameters);
8441 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8442 sig->ret = &mono_defaults.void_class->byval_arg;
8447 * LOCKING: Assumes the loader lock is held.
8449 static MonoMethodSignature*
8450 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8451 MonoMethodSignature *sig;
8453 sig = parameters_to_signature (image, method->parameters);
8454 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8455 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8456 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8460 static MonoMethodSignature*
8461 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8462 MonoMethodSignature *sig;
8464 sig = parameters_to_signature (NULL, method->parameters);
8465 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8466 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8467 sig->generic_param_count = 0;
8472 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8474 MonoClass *klass = mono_object_class (prop);
8475 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8476 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8477 *name = mono_string_to_utf8 (pb->name);
8478 *type = pb->type->type;
8480 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8481 *name = g_strdup (p->property->name);
8482 if (p->property->get)
8483 *type = mono_method_signature (p->property->get)->ret;
8485 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8490 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8492 MonoClass *klass = mono_object_class (field);
8493 if (strcmp (klass->name, "FieldBuilder") == 0) {
8494 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8495 *name = mono_string_to_utf8 (fb->name);
8496 *type = fb->type->type;
8498 MonoReflectionField *f = (MonoReflectionField *)field;
8499 *name = g_strdup (mono_field_get_name (f->field));
8500 *type = f->field->type;
8505 * Encode a value in a custom attribute stream of bytes.
8506 * The value to encode is either supplied as an object in argument val
8507 * (valuetypes are boxed), or as a pointer to the data in the
8509 * @type represents the type of the value
8510 * @buffer is the start of the buffer
8511 * @p the current position in the buffer
8512 * @buflen contains the size of the buffer and is used to return the new buffer size
8513 * if this needs to be realloced.
8514 * @retbuffer and @retp return the start and the position of the buffer
8517 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8519 MonoTypeEnum simple_type;
8521 if ((p-buffer) + 10 >= *buflen) {
8524 newbuf = g_realloc (buffer, *buflen);
8525 p = newbuf + (p-buffer);
8529 argval = ((char*)arg + sizeof (MonoObject));
8530 simple_type = type->type;
8532 switch (simple_type) {
8533 case MONO_TYPE_BOOLEAN:
8538 case MONO_TYPE_CHAR:
8541 swap_with_size (p, argval, 2, 1);
8547 swap_with_size (p, argval, 4, 1);
8551 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8561 swap_with_size (p, argval, 8, 1);
8567 swap_with_size (p, argval, 8, 1);
8570 case MONO_TYPE_VALUETYPE:
8571 if (type->data.klass->enumtype) {
8572 simple_type = mono_class_enum_basetype (type->data.klass)->type;
8575 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8578 case MONO_TYPE_STRING: {
8585 str = mono_string_to_utf8 ((MonoString*)arg);
8586 slen = strlen (str);
8587 if ((p-buffer) + 10 + slen >= *buflen) {
8591 newbuf = g_realloc (buffer, *buflen);
8592 p = newbuf + (p-buffer);
8595 mono_metadata_encode_value (slen, p, &p);
8596 memcpy (p, str, slen);
8601 case MONO_TYPE_CLASS: {
8609 k = mono_object_class (arg);
8610 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8611 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8612 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8615 if (rt && (rtc = mono_object_class (rt)) &&
8616 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8617 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8618 arg = (MonoObject *) rt;
8621 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8624 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8625 slen = strlen (str);
8626 if ((p-buffer) + 10 + slen >= *buflen) {
8630 newbuf = g_realloc (buffer, *buflen);
8631 p = newbuf + (p-buffer);
8634 mono_metadata_encode_value (slen, p, &p);
8635 memcpy (p, str, slen);
8640 case MONO_TYPE_SZARRAY: {
8642 MonoClass *eclass, *arg_eclass;
8645 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8648 len = mono_array_length ((MonoArray*)arg);
8650 *p++ = (len >> 8) & 0xff;
8651 *p++ = (len >> 16) & 0xff;
8652 *p++ = (len >> 24) & 0xff;
8654 *retbuffer = buffer;
8655 eclass = type->data.klass;
8656 arg_eclass = mono_object_class (arg)->element_class;
8659 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8660 eclass = mono_defaults.object_class;
8662 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8663 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8664 int elsize = mono_class_array_element_size (arg_eclass);
8665 for (i = 0; i < len; ++i) {
8666 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8669 } else if (eclass->valuetype && arg_eclass->valuetype) {
8670 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8671 int elsize = mono_class_array_element_size (eclass);
8672 for (i = 0; i < len; ++i) {
8673 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8677 for (i = 0; i < len; ++i) {
8678 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8683 case MONO_TYPE_OBJECT: {
8689 * The parameter type is 'object' but the type of the actual
8690 * argument is not. So we have to add type information to the blob
8691 * too. This is completely undocumented in the spec.
8695 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8700 klass = mono_object_class (arg);
8702 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8705 } else if (klass->enumtype) {
8707 } else if (klass == mono_defaults.string_class) {
8708 simple_type = MONO_TYPE_STRING;
8711 } else if (klass->rank == 1) {
8713 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8714 /* See Partition II, Appendix B3 */
8717 *p++ = klass->element_class->byval_arg.type;
8718 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8720 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8721 *p++ = simple_type = klass->byval_arg.type;
8724 g_error ("unhandled type in custom attr");
8726 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8727 slen = strlen (str);
8728 if ((p-buffer) + 10 + slen >= *buflen) {
8732 newbuf = g_realloc (buffer, *buflen);
8733 p = newbuf + (p-buffer);
8736 mono_metadata_encode_value (slen, p, &p);
8737 memcpy (p, str, slen);
8740 simple_type = mono_class_enum_basetype (klass)->type;
8744 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8747 *retbuffer = buffer;
8751 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8753 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8754 char *str = type_get_qualified_name (type, NULL);
8755 int slen = strlen (str);
8759 * This seems to be optional...
8762 mono_metadata_encode_value (slen, p, &p);
8763 memcpy (p, str, slen);
8766 } else if (type->type == MONO_TYPE_OBJECT) {
8768 } else if (type->type == MONO_TYPE_CLASS) {
8769 /* it should be a type: encode_cattr_value () has the check */
8772 mono_metadata_encode_value (type->type, p, &p);
8773 if (type->type == MONO_TYPE_SZARRAY)
8774 /* See the examples in Partition VI, Annex B */
8775 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8782 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8785 /* Preallocate a large enough buffer */
8786 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8787 char *str = type_get_qualified_name (type, NULL);
8790 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8791 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8797 len += strlen (name);
8799 if ((p-buffer) + 20 + len >= *buflen) {
8803 newbuf = g_realloc (buffer, *buflen);
8804 p = newbuf + (p-buffer);
8808 encode_field_or_prop_type (type, p, &p);
8810 len = strlen (name);
8811 mono_metadata_encode_value (len, p, &p);
8812 memcpy (p, name, len);
8814 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8816 *retbuffer = buffer;
8819 #ifndef DISABLE_REFLECTION_EMIT
8822 * mono_reflection_get_custom_attrs_blob:
8823 * @ctor: custom attribute constructor
8824 * @ctorArgs: arguments o the constructor
8830 * Creates the blob of data that needs to be saved in the metadata and that represents
8831 * the custom attributed described by @ctor, @ctorArgs etc.
8832 * Returns: a Byte array representing the blob of data.
8835 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8838 MonoMethodSignature *sig;
8843 MONO_ARCH_SAVE_REGS;
8845 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8846 /* sig is freed later so allocate it in the heap */
8847 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8849 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8852 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8854 p = buffer = g_malloc (buflen);
8855 /* write the prolog */
8858 for (i = 0; i < sig->param_count; ++i) {
8859 arg = mono_array_get (ctorArgs, MonoObject*, i);
8860 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8864 i += mono_array_length (properties);
8866 i += mono_array_length (fields);
8868 *p++ = (i >> 8) & 0xff;
8871 for (i = 0; i < mono_array_length (properties); ++i) {
8875 prop = mono_array_get (properties, gpointer, i);
8876 get_prop_name_and_type (prop, &pname, &ptype);
8877 *p++ = 0x54; /* PROPERTY signature */
8878 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8885 for (i = 0; i < mono_array_length (fields); ++i) {
8889 field = mono_array_get (fields, gpointer, i);
8890 get_field_name_and_type (field, &fname, &ftype);
8891 *p++ = 0x53; /* FIELD signature */
8892 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8897 g_assert (p - buffer <= buflen);
8898 buflen = p - buffer;
8899 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8900 p = mono_array_addr (result, char, 0);
8901 memcpy (p, buffer, buflen);
8903 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8909 * mono_reflection_setup_internal_class:
8910 * @tb: a TypeBuilder object
8912 * Creates a MonoClass that represents the TypeBuilder.
8913 * This is a trick that lets us simplify a lot of reflection code
8914 * (and will allow us to support Build and Run assemblies easier).
8917 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8919 MonoClass *klass, *parent;
8921 MONO_ARCH_SAVE_REGS;
8923 mono_loader_lock ();
8926 /* check so we can compile corlib correctly */
8927 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8928 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8929 parent = tb->parent->type->data.klass;
8931 parent = my_mono_class_from_mono_type (tb->parent->type);
8937 /* the type has already being created: it means we just have to change the parent */
8938 if (tb->type.type) {
8939 klass = mono_class_from_mono_type (tb->type.type);
8940 klass->parent = NULL;
8941 /* fool mono_class_setup_parent */
8942 klass->supertypes = NULL;
8943 mono_class_setup_parent (klass, parent);
8944 mono_class_setup_mono_type (klass);
8945 mono_loader_unlock ();
8949 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
8951 klass->image = &tb->module->dynamic_image->image;
8953 klass->inited = 1; /* we lie to the runtime */
8954 klass->name = mono_string_to_utf8_image (klass->image, tb->name);
8955 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace);
8956 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8957 klass->flags = tb->attrs;
8959 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8961 klass->element_class = klass;
8963 MOVING_GC_REGISTER (&klass->reflection_info);
8964 klass->reflection_info = tb;
8966 /* Put into cache so mono_class_get () will find it */
8967 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8969 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8970 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8972 if (parent != NULL) {
8973 mono_class_setup_parent (klass, parent);
8974 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8975 const char *old_n = klass->name;
8976 /* trick to get relative numbering right when compiling corlib */
8977 klass->name = "BuildingObject";
8978 mono_class_setup_parent (klass, mono_defaults.object_class);
8979 klass->name = old_n;
8982 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8983 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8984 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8985 klass->instance_size = sizeof (MonoObject);
8986 klass->size_inited = 1;
8987 mono_class_setup_vtable_general (klass, NULL, 0);
8990 mono_class_setup_mono_type (klass);
8992 mono_class_setup_supertypes (klass);
8995 * FIXME: handle interfaces.
8998 tb->type.type = &klass->byval_arg;
9000 if (tb->nesting_type) {
9001 g_assert (tb->nesting_type->type);
9002 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
9005 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9007 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9009 mono_loader_unlock ();
9013 * mono_reflection_setup_generic_class:
9014 * @tb: a TypeBuilder object
9016 * Setup the generic class before adding the first generic parameter.
9019 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9024 * mono_reflection_create_generic_class:
9025 * @tb: a TypeBuilder object
9027 * Creates the generic class after all generic parameters have been added.
9030 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9035 MONO_ARCH_SAVE_REGS;
9037 klass = my_mono_class_from_mono_type (tb->type.type);
9039 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9041 if (klass->generic_container || (count == 0))
9044 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9046 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9048 klass->generic_container->owner.klass = klass;
9049 klass->generic_container->type_argc = count;
9050 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParam) * count);
9052 klass->is_generic = 1;
9054 for (i = 0; i < count; i++) {
9055 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9056 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
9057 /*Make sure we are a diferent type instance */
9058 klass->generic_container->type_params [i].owner = klass->generic_container;
9059 klass->generic_container->type_params [i].pklass = NULL;
9061 g_assert (klass->generic_container->type_params [i].owner);
9064 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9068 * mono_reflection_create_internal_class:
9069 * @tb: a TypeBuilder object
9071 * Actually create the MonoClass that is associated with the TypeBuilder.
9074 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9078 MONO_ARCH_SAVE_REGS;
9080 klass = my_mono_class_from_mono_type (tb->type.type);
9082 mono_loader_lock ();
9083 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9084 MonoReflectionFieldBuilder *fb;
9086 MonoType *enum_basetype;
9088 g_assert (tb->fields != NULL);
9089 g_assert (mono_array_length (tb->fields) >= 1);
9091 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9093 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
9094 mono_loader_unlock ();
9098 enum_basetype = fb->type->type;
9099 klass->element_class = my_mono_class_from_mono_type (enum_basetype);
9100 if (!klass->element_class)
9101 klass->element_class = mono_class_from_mono_type (enum_basetype);
9104 * get the element_class from the current corlib.
9106 ec = default_class_from_mono_type (enum_basetype);
9107 klass->instance_size = ec->instance_size;
9108 klass->size_inited = 1;
9110 * this is almost safe to do with enums and it's needed to be able
9111 * to create objects of the enum type (for use in SetConstant).
9113 /* FIXME: Does this mean enums can't have method overrides ? */
9114 mono_class_setup_vtable_general (klass, NULL, 0);
9116 mono_loader_unlock ();
9119 #endif /* DISABLE_REFLECTION_EMIT */
9121 static MonoMarshalSpec*
9122 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9123 MonoReflectionMarshal *minfo)
9125 MonoMarshalSpec *res;
9127 res = image_g_new0 (image, MonoMarshalSpec, 1);
9128 res->native = minfo->type;
9130 switch (minfo->type) {
9131 case MONO_NATIVE_LPARRAY:
9132 res->data.array_data.elem_type = minfo->eltype;
9133 if (minfo->has_size) {
9134 res->data.array_data.param_num = minfo->param_num;
9135 res->data.array_data.num_elem = minfo->count;
9136 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9139 res->data.array_data.param_num = -1;
9140 res->data.array_data.num_elem = -1;
9141 res->data.array_data.elem_mult = -1;
9145 case MONO_NATIVE_BYVALTSTR:
9146 case MONO_NATIVE_BYVALARRAY:
9147 res->data.array_data.num_elem = minfo->count;
9150 case MONO_NATIVE_CUSTOM:
9151 if (minfo->marshaltyperef)
9152 res->data.custom_data.custom_name =
9153 type_get_fully_qualified_name (minfo->marshaltyperef->type);
9155 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9165 MonoReflectionMarshal*
9166 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9167 MonoMarshalSpec *spec)
9169 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9170 MonoReflectionMarshal *minfo;
9173 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9174 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9175 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9176 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9179 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9180 minfo->type = spec->native;
9182 switch (minfo->type) {
9183 case MONO_NATIVE_LPARRAY:
9184 minfo->eltype = spec->data.array_data.elem_type;
9185 minfo->count = spec->data.array_data.num_elem;
9186 minfo->param_num = spec->data.array_data.param_num;
9189 case MONO_NATIVE_BYVALTSTR:
9190 case MONO_NATIVE_BYVALARRAY:
9191 minfo->count = spec->data.array_data.num_elem;
9194 case MONO_NATIVE_CUSTOM:
9195 if (spec->data.custom_data.custom_name) {
9196 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9198 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9200 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9202 if (spec->data.custom_data.cookie)
9203 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9214 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9215 ReflectionMethodBuilder *rmb,
9216 MonoMethodSignature *sig)
9219 MonoMethodNormal *pm;
9220 MonoMarshalSpec **specs;
9221 MonoReflectionMethodAux *method_aux;
9227 * Methods created using a MethodBuilder should have their memory allocated
9228 * inside the image mempool, while dynamic methods should have their memory
9231 dynamic = rmb->refs != NULL;
9232 image = dynamic ? NULL : klass->image;
9235 g_assert (!klass->generic_class);
9237 mono_loader_lock ();
9239 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9240 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9241 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9243 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9245 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9247 pm = (MonoMethodNormal*)m;
9249 m->dynamic = dynamic;
9251 m->flags = rmb->attrs;
9252 m->iflags = rmb->iattrs;
9253 m->name = mono_string_to_utf8_image (image, rmb->name);
9256 m->skip_visibility = rmb->skip_visibility;
9258 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9260 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9261 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9264 m->signature->pinvoke = 1;
9265 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9266 m->signature->pinvoke = 1;
9268 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9270 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry) : image_strdup (image, m->name);
9271 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll);
9273 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9275 if (klass->image->dynamic)
9276 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9278 mono_loader_unlock ();
9281 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9282 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9283 MonoMethodHeader *header;
9285 gint32 max_stack, i;
9286 gint32 num_locals = 0;
9287 gint32 num_clauses = 0;
9291 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9292 code_size = rmb->ilgen->code_len;
9293 max_stack = rmb->ilgen->max_stack;
9294 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9295 if (rmb->ilgen->ex_handlers)
9296 num_clauses = method_count_clauses (rmb->ilgen);
9299 code = mono_array_addr (rmb->code, guint8, 0);
9300 code_size = mono_array_length (rmb->code);
9301 /* we probably need to run a verifier on the code... */
9311 header = image_g_malloc0 (image, sizeof (MonoMethodHeader) +
9312 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9313 header->code_size = code_size;
9314 header->code = image_g_malloc (image, code_size);
9315 memcpy ((char*)header->code, code, code_size);
9316 header->max_stack = max_stack;
9317 header->init_locals = rmb->init_locals;
9318 header->num_locals = num_locals;
9320 for (i = 0; i < num_locals; ++i) {
9321 MonoReflectionLocalBuilder *lb =
9322 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9324 header->locals [i] = image_g_new0 (image, MonoType, 1);
9325 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9328 header->num_clauses = num_clauses;
9330 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9331 rmb->ilgen, num_clauses);
9334 pm->header = header;
9337 if (rmb->generic_params) {
9338 int count = mono_array_length (rmb->generic_params);
9339 MonoGenericContainer *container;
9341 container = rmb->generic_container;
9343 m->is_generic = TRUE;
9344 mono_method_set_generic_container (m, container);
9346 container->type_argc = count;
9347 container->type_params = image_g_new0 (image, MonoGenericParam, count);
9348 container->owner.method = m;
9350 for (i = 0; i < count; i++) {
9351 MonoReflectionGenericParam *gp =
9352 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9354 container->type_params [i] = *gp->type.type->data.generic_param;
9357 if (klass->generic_container) {
9358 container->parent = klass->generic_container;
9359 container->context.class_inst = klass->generic_container->context.class_inst;
9361 container->context.method_inst = mono_get_shared_generic_inst (container);
9365 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9369 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9371 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9372 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9373 for (i = 0; i < rmb->nrefs; ++i)
9374 data [i + 1] = rmb->refs [i];
9379 /* Parameter info */
9382 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9383 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9384 for (i = 0; i <= m->signature->param_count; ++i) {
9385 MonoReflectionParamBuilder *pb;
9386 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9387 if ((i > 0) && (pb->attrs)) {
9388 /* Make a copy since it might point to a shared type structure */
9389 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9390 m->signature->params [i - 1]->attrs = pb->attrs;
9393 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9394 MonoDynamicImage *assembly;
9395 guint32 idx, def_type, len;
9399 if (!method_aux->param_defaults) {
9400 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9401 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9403 assembly = (MonoDynamicImage*)klass->image;
9404 idx = encode_constant (assembly, pb->def_value, &def_type);
9405 /* Copy the data from the blob since it might get realloc-ed */
9406 p = assembly->blob.data + idx;
9407 len = mono_metadata_decode_blob_size (p, &p2);
9409 method_aux->param_defaults [i] = image_g_malloc (image, len);
9410 method_aux->param_default_types [i] = def_type;
9411 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9415 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name);
9417 if (!method_aux->param_cattr)
9418 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9419 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9425 /* Parameter marshalling */
9428 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9429 MonoReflectionParamBuilder *pb;
9430 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9431 if (pb->marshal_info) {
9433 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9434 specs [pb->position] =
9435 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9439 if (specs != NULL) {
9441 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9442 method_aux->param_marshall = specs;
9445 if (klass->image->dynamic && method_aux)
9446 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9448 mono_loader_unlock ();
9454 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9456 ReflectionMethodBuilder rmb;
9457 MonoMethodSignature *sig;
9459 mono_loader_lock ();
9460 sig = ctor_builder_to_signature (klass->image, mb);
9461 mono_loader_unlock ();
9463 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9465 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9466 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9468 /* If we are in a generic class, we might be called multiple times from inflate_method */
9469 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9470 /* ilgen is no longer needed */
9478 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9480 ReflectionMethodBuilder rmb;
9481 MonoMethodSignature *sig;
9483 mono_loader_lock ();
9484 sig = method_builder_to_signature (klass->image, mb);
9485 mono_loader_unlock ();
9487 reflection_methodbuilder_from_method_builder (&rmb, mb);
9489 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9490 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9492 /* If we are in a generic class, we might be called multiple times from inflate_method */
9493 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9494 /* ilgen is no longer needed */
9500 static MonoClassField*
9501 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9503 MonoClassField *field;
9506 field = g_new0 (MonoClassField, 1);
9508 field->name = mono_string_to_utf8 (fb->name);
9509 if (fb->attrs || fb->modreq || fb->modopt) {
9510 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9511 field->type->attrs = fb->attrs;
9513 g_assert (klass->image->dynamic);
9514 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9515 g_free (field->type);
9516 field->type = custom;
9518 field->type = fb->type->type;
9520 if (fb->offset != -1)
9521 field->offset = fb->offset;
9522 field->parent = klass;
9523 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9525 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9531 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9534 MonoReflectionTypeBuilder *tb = NULL;
9535 gboolean is_dynamic = FALSE;
9539 mono_loader_lock ();
9541 domain = mono_object_domain (type);
9543 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9544 tb = (MonoReflectionTypeBuilder *) type;
9547 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9548 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9550 tb = rgi->generic_type;
9554 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9555 if (tb && tb->generic_container)
9556 mono_reflection_create_generic_class (tb);
9558 klass = mono_class_from_mono_type (type->type);
9559 if (!klass->generic_container) {
9560 mono_loader_unlock ();
9564 if (klass->wastypebuilder) {
9565 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9570 mono_loader_unlock ();
9572 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9574 return &geninst->byval_arg;
9578 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9580 MonoGenericClass *gclass;
9581 MonoGenericInst *inst;
9583 g_assert (klass->generic_container);
9585 inst = mono_metadata_get_generic_inst (type_argc, types);
9586 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9588 return mono_generic_class_get_class (gclass);
9591 MonoReflectionMethod*
9592 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9595 MonoMethod *method, *inflated;
9596 MonoMethodInflated *imethod;
9597 MonoReflectionMethodBuilder *mb = NULL;
9598 MonoGenericContext tmp_context;
9599 MonoGenericInst *ginst;
9600 MonoType **type_argv;
9603 MONO_ARCH_SAVE_REGS;
9605 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9606 #ifndef DISABLE_REFLECTION_EMIT
9607 MonoReflectionTypeBuilder *tb;
9610 mb = (MonoReflectionMethodBuilder *) rmethod;
9611 tb = (MonoReflectionTypeBuilder *) mb->type;
9612 klass = mono_class_from_mono_type (tb->type.type);
9614 method = methodbuilder_to_mono_method (klass, mb);
9616 g_assert_not_reached ();
9620 method = rmethod->method;
9623 klass = method->klass;
9625 if (method->is_inflated)
9626 method = ((MonoMethodInflated *) method)->declaring;
9628 count = mono_method_signature (method)->generic_param_count;
9629 if (count != mono_array_length (types))
9632 type_argv = g_new0 (MonoType *, count);
9633 for (i = 0; i < count; i++) {
9634 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9635 type_argv [i] = garg->type;
9637 ginst = mono_metadata_get_generic_inst (count, type_argv);
9640 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9641 tmp_context.method_inst = ginst;
9643 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9644 imethod = (MonoMethodInflated *) inflated;
9646 if (method->klass->image->dynamic) {
9647 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9649 * This table maps metadata structures representing inflated methods/fields
9650 * to the reflection objects representing their generic definitions.
9652 mono_loader_lock ();
9653 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9654 mono_loader_unlock ();
9657 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9660 #ifndef DISABLE_REFLECTION_EMIT
9663 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9665 MonoMethodInflated *imethod;
9666 MonoGenericContext *context;
9670 * With generic code sharing the klass might not be inflated.
9671 * This can happen because classes inflated with their own
9672 * type arguments are "normalized" to the uninflated class.
9674 if (!klass->generic_class)
9677 context = mono_class_get_context (klass);
9679 if (klass->method.count) {
9680 /* Find the already created inflated method */
9681 for (i = 0; i < klass->method.count; ++i) {
9682 g_assert (klass->methods [i]->is_inflated);
9683 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9686 g_assert (i < klass->method.count);
9687 imethod = (MonoMethodInflated*)klass->methods [i];
9689 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9692 if (method->is_generic && method->klass->image->dynamic) {
9693 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9695 mono_loader_lock ();
9696 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9697 mono_loader_unlock ();
9699 return (MonoMethod *) imethod;
9703 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9708 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9710 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9711 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9712 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9714 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9715 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9716 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9717 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9718 method = ((MonoReflectionMethod *) obj)->method;
9720 method = NULL; /* prevent compiler warning */
9721 g_assert_not_reached ();
9724 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9727 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9729 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9730 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9733 MonoGenericClass *gclass;
9734 MonoDynamicGenericClass *dgclass;
9735 MonoClass *klass, *gklass;
9738 MONO_ARCH_SAVE_REGS;
9740 klass = mono_class_from_mono_type (type->type.type);
9741 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9742 gclass = type->type.type->data.generic_class;
9744 g_assert (gclass->is_dynamic);
9745 dgclass = (MonoDynamicGenericClass *) gclass;
9747 if (dgclass->initialized)
9750 gklass = gclass->container_class;
9751 mono_class_init (gklass);
9753 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9754 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9755 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9756 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9757 dgclass->count_events = events ? mono_array_length (events) : 0;
9759 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9760 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9761 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9762 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9763 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9764 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
9765 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
9767 for (i = 0; i < dgclass->count_methods; i++) {
9768 MonoObject *obj = mono_array_get (methods, gpointer, i);
9770 dgclass->methods [i] = inflate_method (type, obj);
9773 for (i = 0; i < dgclass->count_ctors; i++) {
9774 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9776 dgclass->ctors [i] = inflate_method (type, obj);
9779 for (i = 0; i < dgclass->count_fields; i++) {
9780 MonoObject *obj = mono_array_get (fields, gpointer, i);
9781 MonoClassField *field, *inflated_field = NULL;
9783 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9784 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9785 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9786 field = ((MonoReflectionField *) obj)->field;
9788 field = NULL; /* prevent compiler warning */
9789 g_assert_not_reached ();
9792 dgclass->fields [i] = *field;
9793 dgclass->fields [i].parent = klass;
9794 dgclass->fields [i].type = mono_class_inflate_generic_type (
9795 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9796 dgclass->field_generic_types [i] = field->type;
9797 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
9798 dgclass->field_objects [i] = obj;
9800 if (inflated_field) {
9801 g_free (inflated_field);
9803 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9807 for (i = 0; i < dgclass->count_properties; i++) {
9808 MonoObject *obj = mono_array_get (properties, gpointer, i);
9809 MonoProperty *property = &dgclass->properties [i];
9811 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9812 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9814 property->parent = klass;
9815 property->attrs = pb->attrs;
9816 property->name = mono_string_to_utf8 (pb->name);
9818 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9820 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9821 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9822 *property = *((MonoReflectionProperty *) obj)->property;
9823 property->name = g_strdup (property->name);
9826 property->get = inflate_mono_method (klass, property->get, NULL);
9828 property->set = inflate_mono_method (klass, property->set, NULL);
9830 g_assert_not_reached ();
9833 for (i = 0; i < dgclass->count_events; i++) {
9834 MonoObject *obj = mono_array_get (events, gpointer, i);
9835 MonoEvent *event = &dgclass->events [i];
9837 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9838 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9840 event->parent = klass;
9841 event->attrs = eb->attrs;
9842 event->name = mono_string_to_utf8 (eb->name);
9844 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9845 if (eb->remove_method)
9846 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9847 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9848 *event = *((MonoReflectionEvent *) obj)->event;
9849 event->name = g_strdup (event->name);
9852 event->add = inflate_mono_method (klass, event->add, NULL);
9854 event->remove = inflate_mono_method (klass, event->remove, NULL);
9856 g_assert_not_reached ();
9859 dgclass->initialized = TRUE;
9863 ensure_generic_class_runtime_vtable (MonoClass *klass)
9865 MonoClass *gklass = klass->generic_class->container_class;
9868 if (klass->wastypebuilder)
9871 ensure_runtime_vtable (gklass);
9873 klass->method.count = gklass->method.count;
9874 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
9876 for (i = 0; i < klass->method.count; i++) {
9877 klass->methods [i] = mono_class_inflate_generic_method_full (
9878 gklass->methods [i], klass, mono_class_get_context (klass));
9881 klass->interface_count = gklass->interface_count;
9882 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9883 for (i = 0; i < klass->interface_count; ++i) {
9884 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
9885 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
9886 mono_metadata_free_type (iface_type);
9888 ensure_runtime_vtable (klass->interfaces [i]);
9890 klass->interfaces_inited = 1;
9892 /*We can only finish with this klass once it's parent has as well*/
9893 if (gklass->wastypebuilder)
9894 klass->wastypebuilder = TRUE;
9899 ensure_runtime_vtable (MonoClass *klass)
9901 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9904 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
9907 ensure_runtime_vtable (klass->parent);
9910 num = tb->ctors? mono_array_length (tb->ctors): 0;
9911 num += tb->num_methods;
9912 klass->method.count = num;
9913 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
9914 num = tb->ctors? mono_array_length (tb->ctors): 0;
9915 for (i = 0; i < num; ++i)
9916 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9917 num = tb->num_methods;
9919 for (i = 0; i < num; ++i)
9920 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9922 if (tb->interfaces) {
9923 klass->interface_count = mono_array_length (tb->interfaces);
9924 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9925 for (i = 0; i < klass->interface_count; ++i) {
9926 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9927 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9928 ensure_runtime_vtable (klass->interfaces [i]);
9930 klass->interfaces_inited = 1;
9932 } else if (klass->generic_class){
9933 ensure_generic_class_runtime_vtable (klass);
9936 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9937 for (i = 0; i < klass->method.count; ++i)
9938 klass->methods [i]->slot = i;
9940 mono_class_setup_interface_offsets (klass);
9941 mono_class_setup_interface_id (klass);
9945 * The generic vtable is needed even if image->run is not set since some
9946 * runtime code like ves_icall_Type_GetMethodsByName depends on
9947 * method->slot being defined.
9951 * tb->methods could not be freed since it is used for determining
9952 * overrides during dynamic vtable construction.
9957 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9959 MonoReflectionTypeBuilder *tb;
9965 g_assert (klass->image->dynamic);
9967 if (!klass->reflection_info)
9970 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9972 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9976 for (i = 0; i < tb->num_methods; ++i) {
9977 MonoReflectionMethodBuilder *mb =
9978 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9979 if (mb->override_method)
9985 *overrides = g_new0 (MonoMethod*, onum * 2);
9988 for (i = 0; i < tb->num_methods; ++i) {
9989 MonoReflectionMethodBuilder *mb =
9990 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9991 if (mb->override_method) {
9992 (*overrides) [onum * 2] =
9993 mb->override_method->method;
9994 (*overrides) [onum * 2 + 1] =
9997 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9998 g_assert (mb->override_method->method);
9999 g_assert (mb->mhandle);
10006 *num_overrides = onum;
10010 typebuilder_setup_fields (MonoClass *klass)
10012 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10013 MonoReflectionFieldBuilder *fb;
10014 MonoClassField *field;
10015 MonoImage *image = klass->image;
10016 const char *p, *p2;
10018 guint32 len, idx, real_size = 0;
10020 klass->field.count = tb->num_fields;
10021 klass->field.first = 0;
10023 if (tb->class_size) {
10024 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10025 klass->packing_size = tb->packing_size;
10026 real_size = klass->instance_size + tb->class_size;
10029 if (!klass->field.count) {
10030 klass->instance_size = MAX (klass->instance_size, real_size);
10034 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10035 mono_class_alloc_ext (klass);
10036 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10038 for (i = 0; i < klass->field.count; ++i) {
10039 fb = mono_array_get (tb->fields, gpointer, i);
10040 field = &klass->fields [i];
10041 field->name = mono_string_to_utf8_image (image, fb->name);
10043 field->type = mono_metadata_type_dup (klass->image, fb->type->type);
10044 field->type->attrs = fb->attrs;
10046 field->type = fb->type->type;
10048 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10049 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10050 if (fb->offset != -1)
10051 field->offset = fb->offset;
10052 field->parent = klass;
10053 fb->handle = field;
10054 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10056 if (fb->def_value) {
10057 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10058 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10059 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10060 /* Copy the data from the blob since it might get realloc-ed */
10061 p = assembly->blob.data + idx;
10062 len = mono_metadata_decode_blob_size (p, &p2);
10064 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10065 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10069 klass->instance_size = MAX (klass->instance_size, real_size);
10070 mono_class_layout_fields (klass);
10074 typebuilder_setup_properties (MonoClass *klass)
10076 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10077 MonoReflectionPropertyBuilder *pb;
10078 MonoImage *image = klass->image;
10079 MonoProperty *properties;
10083 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10085 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10086 klass->ext->property.first = 0;
10088 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10089 klass->ext->properties = properties;
10090 for (i = 0; i < klass->ext->property.count; ++i) {
10091 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10092 properties [i].parent = klass;
10093 properties [i].attrs = pb->attrs;
10094 properties [i].name = mono_string_to_utf8_image (image, pb->name);
10095 if (pb->get_method)
10096 properties [i].get = pb->get_method->mhandle;
10097 if (pb->set_method)
10098 properties [i].set = pb->set_method->mhandle;
10100 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10104 MonoReflectionEvent *
10105 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10107 MonoEvent *event = g_new0 (MonoEvent, 1);
10111 klass = my_mono_class_from_mono_type (tb->type.type);
10113 event->parent = klass;
10114 event->attrs = eb->attrs;
10115 event->name = mono_string_to_utf8 (eb->name);
10116 if (eb->add_method)
10117 event->add = eb->add_method->mhandle;
10118 if (eb->remove_method)
10119 event->remove = eb->remove_method->mhandle;
10120 if (eb->raise_method)
10121 event->raise = eb->raise_method->mhandle;
10123 if (eb->other_methods) {
10124 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10125 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10126 MonoReflectionMethodBuilder *mb =
10127 mono_array_get (eb->other_methods,
10128 MonoReflectionMethodBuilder*, j);
10129 event->other [j] = mb->mhandle;
10133 return mono_event_get_object (mono_object_domain (tb), klass, event);
10137 typebuilder_setup_events (MonoClass *klass)
10139 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10140 MonoReflectionEventBuilder *eb;
10141 MonoImage *image = klass->image;
10146 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10148 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10149 klass->ext->event.first = 0;
10151 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10152 klass->ext->events = events;
10153 for (i = 0; i < klass->ext->event.count; ++i) {
10154 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10155 events [i].parent = klass;
10156 events [i].attrs = eb->attrs;
10157 events [i].name = mono_string_to_utf8_image (image, eb->name);
10158 if (eb->add_method)
10159 events [i].add = eb->add_method->mhandle;
10160 if (eb->remove_method)
10161 events [i].remove = eb->remove_method->mhandle;
10162 if (eb->raise_method)
10163 events [i].raise = eb->raise_method->mhandle;
10165 if (eb->other_methods) {
10166 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10167 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10168 MonoReflectionMethodBuilder *mb =
10169 mono_array_get (eb->other_methods,
10170 MonoReflectionMethodBuilder*, j);
10171 events [i].other [j] = mb->mhandle;
10174 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10179 remove_instantiations_of (gpointer key,
10181 gpointer user_data)
10183 MonoType *type = (MonoType*)key;
10184 MonoClass *klass = (MonoClass*)user_data;
10186 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10192 MonoReflectionType*
10193 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10196 MonoDomain* domain;
10197 MonoReflectionType* res;
10200 MONO_ARCH_SAVE_REGS;
10202 domain = mono_object_domain (tb);
10203 klass = my_mono_class_from_mono_type (tb->type.type);
10205 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10208 * we need to lock the domain because the lock will be taken inside
10209 * So, we need to keep the locking order correct.
10211 mono_domain_lock (domain);
10212 mono_loader_lock ();
10213 if (klass->wastypebuilder) {
10214 mono_loader_unlock ();
10215 mono_domain_unlock (domain);
10216 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10219 * Fields to set in klass:
10220 * the various flags: delegate/unicode/contextbound etc.
10222 klass->flags = tb->attrs;
10223 klass->has_cctor = 1;
10224 klass->has_finalize = 1;
10227 if (!((MonoDynamicImage*)klass->image)->run) {
10228 if (klass->generic_container) {
10229 /* FIXME: The code below can't handle generic classes */
10230 klass->wastypebuilder = TRUE;
10231 mono_loader_unlock ();
10232 mono_domain_unlock (domain);
10233 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10238 /* enums are done right away */
10239 if (!klass->enumtype)
10240 ensure_runtime_vtable (klass);
10242 if (tb->subtypes) {
10243 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10244 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10245 mono_class_alloc_ext (klass);
10246 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
10250 klass->nested_classes_inited = TRUE;
10252 /* fields and object layout */
10253 if (klass->parent) {
10254 if (!klass->parent->size_inited)
10255 mono_class_init (klass->parent);
10256 klass->instance_size = klass->parent->instance_size;
10257 klass->sizes.class_size = 0;
10258 klass->min_align = klass->parent->min_align;
10259 /* if the type has no fields we won't call the field_setup
10260 * routine which sets up klass->has_references.
10262 klass->has_references |= klass->parent->has_references;
10264 klass->instance_size = sizeof (MonoObject);
10265 klass->min_align = 1;
10268 /* FIXME: handle packing_size and instance_size */
10269 typebuilder_setup_fields (klass);
10271 typebuilder_setup_properties (klass);
10273 typebuilder_setup_events (klass);
10275 klass->wastypebuilder = TRUE;
10278 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10279 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10280 * we want to return normal System.MonoType objects, so clear these out from the cache.
10282 if (domain->type_hash && klass->generic_container)
10283 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10285 mono_loader_unlock ();
10286 mono_domain_unlock (domain);
10288 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10289 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10290 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10293 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10294 g_assert (res != (MonoReflectionType*)tb);
10300 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10302 MonoGenericParam *param;
10305 MONO_ARCH_SAVE_REGS;
10307 param = g_new0 (MonoGenericParam, 1);
10309 if (gparam->mbuilder) {
10310 if (!gparam->mbuilder->generic_container) {
10311 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10312 MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
10313 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10314 gparam->mbuilder->generic_container->is_method = TRUE;
10316 param->owner = gparam->mbuilder->generic_container;
10317 } else if (gparam->tbuilder) {
10318 if (!gparam->tbuilder->generic_container) {
10319 MonoClass *klass = my_mono_class_from_mono_type (gparam->tbuilder->type.type);
10320 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10321 gparam->tbuilder->generic_container->owner.klass = klass;
10323 param->owner = gparam->tbuilder->generic_container;
10326 param->name = mono_string_to_utf8 (gparam->name);
10327 param->num = gparam->index;
10329 image = &gparam->tbuilder->module->dynamic_image->image;
10330 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10332 gparam->type.type = ¶m->pklass->byval_arg;
10334 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
10335 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10339 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10341 MonoDynamicImage *assembly = sig->module->dynamic_image;
10342 guint32 na = mono_array_length (sig->arguments);
10347 sigbuffer_init (&buf, 32);
10349 sigbuffer_add_value (&buf, 0x07);
10350 sigbuffer_add_value (&buf, na);
10351 for (i = 0; i < na; ++i) {
10352 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10353 encode_reflection_type (assembly, type, &buf);
10356 buflen = buf.p - buf.buf;
10357 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10358 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10359 sigbuffer_free (&buf);
10365 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10367 MonoDynamicImage *assembly = sig->module->dynamic_image;
10368 guint32 na = mono_array_length (sig->arguments);
10373 sigbuffer_init (&buf, 32);
10375 sigbuffer_add_value (&buf, 0x06);
10376 for (i = 0; i < na; ++i) {
10377 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10378 encode_reflection_type (assembly, type, &buf);
10381 buflen = buf.p - buf.buf;
10382 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10383 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10384 sigbuffer_free (&buf);
10390 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10392 ReflectionMethodBuilder rmb;
10393 MonoMethodSignature *sig;
10398 sig = dynamic_method_to_signature (mb);
10400 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10403 * Resolve references.
10406 * Every second entry in the refs array is reserved for storing handle_class,
10407 * which is needed by the ldtoken implementation in the JIT.
10409 rmb.nrefs = mb->nrefs;
10410 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10411 for (i = 0; i < mb->nrefs; i += 2) {
10412 MonoClass *handle_class;
10414 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10416 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10417 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10419 * The referenced DynamicMethod should already be created by the managed
10420 * code, except in the case of circular references. In that case, we store
10421 * method in the refs array, and fix it up later when the referenced
10422 * DynamicMethod is created.
10424 if (method->mhandle) {
10425 ref = method->mhandle;
10427 /* FIXME: GC object stored in unmanaged memory */
10430 /* FIXME: GC object stored in unmanaged memory */
10431 method->referenced_by = g_slist_append (method->referenced_by, mb);
10433 handle_class = mono_defaults.methodhandle_class;
10435 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10438 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10443 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10444 rmb.refs [i + 1] = handle_class;
10447 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10449 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10451 /* Fix up refs entries pointing at us */
10452 for (l = mb->referenced_by; l; l = l->next) {
10453 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10454 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10457 g_assert (method->mhandle);
10459 data = (gpointer*)wrapper->method_data;
10460 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10461 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10462 data [i + 1] = mb->mhandle;
10465 g_slist_free (mb->referenced_by);
10469 /* ilgen is no longer needed */
10473 #endif /* DISABLE_REFLECTION_EMIT */
10476 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10481 mono_runtime_free_method (
10482 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10487 * mono_reflection_is_valid_dynamic_token:
10489 * Returns TRUE if token is valid.
10493 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10495 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10498 #ifndef DISABLE_REFLECTION_EMIT
10501 * mono_reflection_lookup_dynamic_token:
10503 * Finish the Builder object pointed to by TOKEN and return the corresponding
10504 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10505 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10508 * LOCKING: Take the loader lock
10511 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10513 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10517 mono_loader_lock ();
10518 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10519 mono_loader_unlock ();
10522 g_assert_not_reached ();
10528 handle_class = &klass;
10529 return resolve_object (image, obj, handle_class, context);
10533 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10535 gpointer result = NULL;
10537 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10538 result = mono_string_intern ((MonoString*)obj);
10539 *handle_class = NULL;
10541 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10542 MonoReflectionType *tb = (MonoReflectionType*)obj;
10544 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10545 result = mono_class_from_mono_type (inflated);
10546 mono_metadata_free_type (inflated);
10548 result = mono_class_from_mono_type (tb->type);
10550 *handle_class = mono_defaults.typehandle_class;
10552 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10553 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10554 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10555 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10556 result = ((MonoReflectionMethod*)obj)->method;
10558 result = mono_class_inflate_generic_method (result, context);
10559 *handle_class = mono_defaults.methodhandle_class;
10561 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10562 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10563 result = mb->mhandle;
10565 /* Type is not yet created */
10566 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10568 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10571 * Hopefully this has been filled in by calling CreateType() on the
10575 * TODO: This won't work if the application finishes another
10576 * TypeBuilder instance instead of this one.
10578 result = mb->mhandle;
10581 result = mono_class_inflate_generic_method (result, context);
10582 *handle_class = mono_defaults.methodhandle_class;
10583 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10584 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10586 result = cb->mhandle;
10588 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10590 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10591 result = cb->mhandle;
10594 result = mono_class_inflate_generic_method (result, context);
10595 *handle_class = mono_defaults.methodhandle_class;
10596 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10597 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10599 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
10600 MonoClass *class = mono_class_from_mono_type (inflated);
10601 MonoClassField *inflated_field;
10602 gpointer iter = NULL;
10603 mono_metadata_free_type (inflated);
10604 while ((inflated_field = mono_class_get_fields (class, &iter))) {
10605 if (!strcmp (field->name, inflated_field->name))
10608 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
10609 result = inflated_field;
10613 *handle_class = mono_defaults.fieldhandle_class;
10615 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10616 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10617 result = fb->handle;
10620 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10622 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10623 result = fb->handle;
10626 if (fb->handle && fb->handle->parent->generic_container) {
10627 MonoClass *klass = fb->handle->parent;
10628 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10629 MonoClass *inflated = mono_class_from_mono_type (type);
10631 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
10633 mono_metadata_free_type (type);
10635 *handle_class = mono_defaults.fieldhandle_class;
10636 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10637 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10640 klass = tb->type.type->data.klass;
10641 if (klass->wastypebuilder) {
10642 /* Already created */
10646 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10647 result = tb->type.type->data.klass;
10650 *handle_class = mono_defaults.typehandle_class;
10651 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10652 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10653 MonoMethodSignature *sig;
10656 if (helper->arguments)
10657 nargs = mono_array_length (helper->arguments);
10661 sig = mono_metadata_signature_alloc (image, nargs);
10662 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10663 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10665 if (helper->call_conv == 0) /* unmanaged */
10666 sig->call_convention = helper->unmanaged_call_conv - 1;
10668 if (helper->call_conv & 0x02)
10669 sig->call_convention = MONO_CALL_VARARG;
10671 sig->call_convention = MONO_CALL_DEFAULT;
10673 sig->param_count = nargs;
10674 /* TODO: Copy type ? */
10675 sig->ret = helper->return_type->type;
10676 for (i = 0; i < nargs; ++i) {
10677 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10678 sig->params [i] = rt->type;
10682 *handle_class = NULL;
10683 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10684 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10685 /* Already created by the managed code */
10686 g_assert (method->mhandle);
10687 result = method->mhandle;
10688 *handle_class = mono_defaults.methodhandle_class;
10689 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10690 MonoReflectionType *tb = (MonoReflectionType*)obj;
10691 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10692 result = mono_class_from_mono_type (type);
10693 *handle_class = mono_defaults.typehandle_class;
10695 mono_metadata_free_type (type);
10696 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10697 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10698 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10699 result = mono_class_from_mono_type (type);
10700 *handle_class = mono_defaults.typehandle_class;
10702 mono_metadata_free_type (type);
10703 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10704 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10705 MonoClass *inflated;
10708 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10709 inflated = mono_class_from_mono_type (type);
10711 g_assert (f->fb->handle);
10712 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
10714 mono_metadata_free_type (type);
10715 *handle_class = mono_defaults.fieldhandle_class;
10716 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10717 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10718 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10719 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10720 g_assert (c->cb->mhandle);
10721 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10722 *handle_class = mono_defaults.methodhandle_class;
10723 mono_metadata_free_type (type);
10724 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10725 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10726 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10727 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10728 g_assert (m->mb->mhandle);
10729 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10730 *handle_class = mono_defaults.methodhandle_class;
10731 mono_metadata_free_type (type);
10733 g_print (obj->vtable->klass->name);
10734 g_assert_not_reached ();
10739 #else /* DISABLE_REFLECTION_EMIT */
10742 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10744 g_assert_not_reached ();
10749 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10751 g_assert_not_reached ();
10755 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10757 g_assert_not_reached ();
10761 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10763 g_assert_not_reached ();
10767 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10769 g_assert_not_reached ();
10773 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
10775 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10779 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
10781 g_assert_not_reached ();
10784 MonoReflectionModule *
10785 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
10787 g_assert_not_reached ();
10792 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
10794 g_assert_not_reached ();
10799 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
10801 g_assert_not_reached ();
10806 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
10807 gboolean create_methodspec, gboolean register_token)
10809 g_assert_not_reached ();
10814 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
10819 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10820 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10823 g_assert_not_reached ();
10827 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10830 *num_overrides = 0;
10833 MonoReflectionEvent *
10834 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10836 g_assert_not_reached ();
10840 MonoReflectionType*
10841 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10843 g_assert_not_reached ();
10848 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10850 g_assert_not_reached ();
10854 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10856 g_assert_not_reached ();
10861 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10863 g_assert_not_reached ();
10868 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10873 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10878 #endif /* DISABLE_REFLECTION_EMIT */
10880 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10881 const static guint32 declsec_flags_map[] = {
10882 0x00000000, /* empty */
10883 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10884 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10885 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10886 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10887 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10888 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10889 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10890 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10891 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10892 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10893 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10894 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10895 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10896 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10897 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10898 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10899 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10900 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10904 * Returns flags that includes all available security action associated to the handle.
10905 * @token: metadata token (either for a class or a method)
10906 * @image: image where resides the metadata.
10909 mono_declsec_get_flags (MonoImage *image, guint32 token)
10911 int index = mono_metadata_declsec_from_index (image, token);
10912 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10913 guint32 result = 0;
10917 /* HasSecurity can be present for other, not specially encoded, attributes,
10918 e.g. SuppressUnmanagedCodeSecurityAttribute */
10922 for (i = index; i < t->rows; i++) {
10923 guint32 cols [MONO_DECL_SECURITY_SIZE];
10925 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10926 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10929 action = cols [MONO_DECL_SECURITY_ACTION];
10930 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10931 result |= declsec_flags_map [action];
10933 g_assert_not_reached ();
10940 * Get the security actions (in the form of flags) associated with the specified method.
10942 * @method: The method for which we want the declarative security flags.
10943 * Return the declarative security flags for the method (only).
10945 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10946 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10949 mono_declsec_flags_from_method (MonoMethod *method)
10951 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10952 /* FIXME: No cache (for the moment) */
10953 guint32 idx = mono_method_get_index (method);
10954 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10955 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10956 return mono_declsec_get_flags (method->klass->image, idx);
10962 * Get the security actions (in the form of flags) associated with the specified class.
10964 * @klass: The class for which we want the declarative security flags.
10965 * Return the declarative security flags for the class.
10967 * Note: We cache the flags inside the MonoClass structure as this will get
10968 * called very often (at least for each method).
10971 mono_declsec_flags_from_class (MonoClass *klass)
10973 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10974 if (!klass->ext || !klass->ext->declsec_flags) {
10977 idx = mono_metadata_token_index (klass->type_token);
10978 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10979 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10980 mono_loader_lock ();
10981 mono_class_alloc_ext (klass);
10982 mono_loader_unlock ();
10983 /* we cache the flags on classes */
10984 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10986 return klass->ext->declsec_flags;
10992 * Get the security actions (in the form of flags) associated with the specified assembly.
10994 * @assembly: The assembly for which we want the declarative security flags.
10995 * Return the declarative security flags for the assembly.
10998 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
11000 guint32 idx = 1; /* there is only one assembly */
11001 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11002 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11003 return mono_declsec_get_flags (assembly->image, idx);
11008 * Fill actions for the specific index (which may either be an encoded class token or
11009 * an encoded method token) from the metadata image.
11010 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11013 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11014 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11016 MonoBoolean result = FALSE;
11018 guint32 cols [MONO_DECL_SECURITY_SIZE];
11019 int index = mono_metadata_declsec_from_index (image, token);
11022 t = &image->tables [MONO_TABLE_DECLSECURITY];
11023 for (i = index; i < t->rows; i++) {
11024 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11026 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11029 /* if present only replace (class) permissions with method permissions */
11030 /* if empty accept either class or method permissions */
11031 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11032 if (!actions->demand.blob) {
11033 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11034 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11035 actions->demand.blob = (char*) (blob + 2);
11036 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11039 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11040 if (!actions->noncasdemand.blob) {
11041 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11042 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11043 actions->noncasdemand.blob = (char*) (blob + 2);
11044 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11047 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11048 if (!actions->demandchoice.blob) {
11049 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11050 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11051 actions->demandchoice.blob = (char*) (blob + 2);
11052 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11062 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
11063 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11065 guint32 idx = mono_metadata_token_index (klass->type_token);
11066 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11067 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11068 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11072 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11073 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11075 guint32 idx = mono_method_get_index (method);
11076 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11077 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11078 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11082 * Collect all actions (that requires to generate code in mini) assigned for
11083 * the specified method.
11084 * Note: Don't use the content of actions if the function return FALSE.
11087 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11089 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11090 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11091 MonoBoolean result = FALSE;
11094 /* quick exit if no declarative security is present in the metadata */
11095 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11098 /* we want the original as the wrapper is "free" of the security informations */
11099 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11100 method = mono_marshal_method_from_wrapper (method);
11105 /* First we look for method-level attributes */
11106 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11107 mono_class_init (method->klass);
11108 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11110 result = mono_declsec_get_method_demands_params (method, demands,
11111 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11114 /* Here we use (or create) the class declarative cache to look for demands */
11115 flags = mono_declsec_flags_from_class (method->klass);
11116 if (flags & mask) {
11118 mono_class_init (method->klass);
11119 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11121 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11122 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11125 /* The boolean return value is used as a shortcut in case nothing needs to
11126 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11132 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11134 * Note: Don't use the content of actions if the function return FALSE.
11137 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11139 MonoBoolean result = FALSE;
11142 /* quick exit if no declarative security is present in the metadata */
11143 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11146 /* we want the original as the wrapper is "free" of the security informations */
11147 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11148 method = mono_marshal_method_from_wrapper (method);
11153 /* results are independant - zeroize both */
11154 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11155 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11157 /* First we look for method-level attributes */
11158 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11159 mono_class_init (method->klass);
11161 result = mono_declsec_get_method_demands_params (method, cmethod,
11162 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11165 /* Here we use (or create) the class declarative cache to look for demands */
11166 flags = mono_declsec_flags_from_class (method->klass);
11167 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11168 mono_class_init (method->klass);
11170 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11171 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11178 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11180 * @klass The inherited class - this is the class that provides the security check (attributes)
11182 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11184 * Note: Don't use the content of actions if the function return FALSE.
11187 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11189 MonoBoolean result = FALSE;
11192 /* quick exit if no declarative security is present in the metadata */
11193 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11196 /* Here we use (or create) the class declarative cache to look for demands */
11197 flags = mono_declsec_flags_from_class (klass);
11198 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11199 mono_class_init (klass);
11200 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11202 result |= mono_declsec_get_class_demands_params (klass, demands,
11203 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11210 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11212 * Note: Don't use the content of actions if the function return FALSE.
11215 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11217 /* quick exit if no declarative security is present in the metadata */
11218 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11221 /* we want the original as the wrapper is "free" of the security informations */
11222 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11223 method = mono_marshal_method_from_wrapper (method);
11228 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11229 mono_class_init (method->klass);
11230 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11232 return mono_declsec_get_method_demands_params (method, demands,
11233 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11240 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11242 guint32 cols [MONO_DECL_SECURITY_SIZE];
11246 int index = mono_metadata_declsec_from_index (image, token);
11250 t = &image->tables [MONO_TABLE_DECLSECURITY];
11251 for (i = index; i < t->rows; i++) {
11252 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11254 /* shortcut - index are ordered */
11255 if (token != cols [MONO_DECL_SECURITY_PARENT])
11258 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11259 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11260 entry->blob = (char*) (metadata + 2);
11261 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11270 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11272 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11273 guint32 idx = mono_method_get_index (method);
11274 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11275 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11276 return get_declsec_action (method->klass->image, idx, action, entry);
11282 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11285 guint32 flags = mono_declsec_flags_from_class (klass);
11286 if (declsec_flags_map [action] & flags) {
11287 guint32 idx = mono_metadata_token_index (klass->type_token);
11288 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11289 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11290 return get_declsec_action (klass->image, idx, action, entry);
11296 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11298 guint32 idx = 1; /* there is only one assembly */
11299 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11300 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11302 return get_declsec_action (assembly->image, idx, action, entry);
11306 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11308 MonoObject *res, *exc;
11310 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11311 static MonoMethod *method = NULL;
11313 if (!System_Reflection_Emit_TypeBuilder) {
11314 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11315 g_assert (System_Reflection_Emit_TypeBuilder);
11317 if (method == NULL) {
11318 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11323 * The result of mono_type_get_object () might be a System.MonoType but we
11324 * need a TypeBuilder so use klass->reflection_info.
11326 g_assert (klass->reflection_info);
11327 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11329 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11331 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11335 return *(MonoBoolean*)mono_object_unbox (res);