2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/gc-internal.h"
17 #include "mono/metadata/tokentype.h"
18 #include "mono/metadata/domain-internals.h"
19 #include "mono/metadata/opcodes.h"
20 #include "mono/metadata/assembly.h"
21 #include "mono/metadata/object-internals.h"
22 #include <mono/metadata/exception.h>
23 #include <mono/metadata/marshal.h>
24 #include <mono/metadata/security-manager.h>
33 #include "rawbuffer.h"
34 #include "mono-endian.h"
35 #include <mono/os/gc_wrapper.h>
37 #define TEXT_OFFSET 512
38 #define CLI_H_SIZE 136
39 #define FILE_ALIGN 512
40 #define VIRT_ALIGN 8192
41 #define START_TEXT_RVA 0x00002000
44 MonoReflectionILGen *ilgen;
45 MonoReflectionType *rtype;
46 MonoArray *parameters;
47 MonoArray *generic_params;
48 MonoGenericContainer *generic_container;
54 guint32 *table_idx; /* note: it's a pointer */
58 MonoBoolean init_locals;
59 MonoBoolean skip_visibility;
60 MonoArray *return_modreq;
61 MonoArray *return_modopt;
62 MonoArray *param_modreq;
63 MonoArray *param_modopt;
64 MonoArray *permissions;
69 int charset, extra_flags, native_cc;
70 MonoString *dll, *dllentry;
71 } ReflectionMethodBuilder;
75 MonoReflectionGenericParam *gparam;
76 } GenericParamTableEntry;
78 const unsigned char table_sizes [MONO_TABLE_NUM] = {
88 MONO_INTERFACEIMPL_SIZE,
89 MONO_MEMBERREF_SIZE, /* 0x0A */
91 MONO_CUSTOM_ATTR_SIZE,
92 MONO_FIELD_MARSHAL_SIZE,
93 MONO_DECL_SECURITY_SIZE,
94 MONO_CLASS_LAYOUT_SIZE,
95 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
96 MONO_STAND_ALONE_SIGNATURE_SIZE,
100 MONO_PROPERTY_MAP_SIZE,
103 MONO_METHOD_SEMA_SIZE,
104 MONO_METHODIMPL_SIZE,
105 MONO_MODULEREF_SIZE, /* 0x1A */
111 MONO_ASSEMBLY_SIZE, /* 0x20 */
112 MONO_ASSEMBLY_PROCESSOR_SIZE,
113 MONO_ASSEMBLYOS_SIZE,
114 MONO_ASSEMBLYREF_SIZE,
115 MONO_ASSEMBLYREFPROC_SIZE,
116 MONO_ASSEMBLYREFOS_SIZE,
120 MONO_NESTED_CLASS_SIZE,
122 MONO_GENERICPARAM_SIZE, /* 0x2A */
123 MONO_METHODSPEC_SIZE,
124 MONO_GENPARCONSTRAINT_SIZE
128 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
129 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
130 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
131 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
132 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
133 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
134 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
135 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
136 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
137 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
138 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
139 static void ensure_runtime_vtable (MonoClass *klass);
140 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class);
141 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
142 static guint32 type_get_signature_size (MonoType *type);
143 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
144 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
145 static inline MonoType *dup_type (const MonoType *original);
150 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
154 mp_g_malloc (MonoMemPool *mp, guint size)
157 return mono_mempool_alloc (mp, size);
159 return g_malloc (size);
165 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
169 mp_g_malloc0 (MonoMemPool *mp, guint size)
172 return mono_mempool_alloc0 (mp, size);
174 return g_malloc0 (size);
177 #define mp_g_new(mp,struct_type, n_structs) \
178 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
180 #define mp_g_new0(mp,struct_type, n_structs) \
181 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
184 alloc_table (MonoDynamicTable *table, guint nrows)
187 g_assert (table->columns);
188 if (nrows + 1 >= table->alloc_rows) {
189 while (nrows + 1 >= table->alloc_rows) {
190 if (table->alloc_rows == 0)
191 table->alloc_rows = 16;
193 table->alloc_rows *= 2;
196 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
201 make_room_in_stream (MonoDynamicStream *stream, int size)
203 if (size <= stream->alloc_size)
206 while (stream->alloc_size <= size) {
207 if (stream->alloc_size < 4096)
208 stream->alloc_size = 4096;
210 stream->alloc_size *= 2;
213 stream->data = g_realloc (stream->data, stream->alloc_size);
217 string_heap_insert (MonoDynamicStream *sh, const char *str)
221 gpointer oldkey, oldval;
223 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
224 return GPOINTER_TO_UINT (oldval);
226 len = strlen (str) + 1;
229 make_room_in_stream (sh, idx + len);
232 * We strdup the string even if we already copy them in sh->data
233 * so that the string pointers in the hash remain valid even if
234 * we need to realloc sh->data. We may want to avoid that later.
236 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
237 memcpy (sh->data + idx, str, len);
243 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
245 char *name = mono_string_to_utf8 (str);
247 idx = string_heap_insert (sh, name);
253 string_heap_init (MonoDynamicStream *sh)
256 sh->alloc_size = 4096;
257 sh->data = g_malloc (4096);
258 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
259 string_heap_insert (sh, "");
263 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
267 make_room_in_stream (stream, stream->index + len);
268 memcpy (stream->data + stream->index, data, len);
270 stream->index += len;
272 * align index? Not without adding an additional param that controls it since
273 * we may store a blob value in pieces.
279 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
283 make_room_in_stream (stream, stream->index + len);
284 memset (stream->data + stream->index, 0, len);
286 stream->index += len;
291 stream_data_align (MonoDynamicStream *stream)
294 guint32 count = stream->index % 4;
296 /* we assume the stream data will be aligned */
298 mono_image_add_stream_data (stream, buf, 4 - count);
302 mono_blob_entry_hash (const char* str)
306 len = mono_metadata_decode_blob_size (str, &str);
310 for (str += 1; str < end; str++)
311 h = (h << 5) - h + *str;
319 mono_blob_entry_equal (const char *str1, const char *str2) {
323 len = mono_metadata_decode_blob_size (str1, &end1);
324 len2 = mono_metadata_decode_blob_size (str2, &end2);
327 return memcmp (end1, end2, len) == 0;
331 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
335 gpointer oldkey, oldval;
337 copy = g_malloc (s1+s2);
338 memcpy (copy, b1, s1);
339 memcpy (copy + s1, b2, s2);
340 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
342 idx = GPOINTER_TO_UINT (oldval);
344 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
345 mono_image_add_stream_data (&assembly->blob, b2, s2);
346 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
352 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
353 * dest may be misaligned.
356 swap_with_size (char *dest, const char* val, int len, int nelem) {
357 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
360 for (elem = 0; elem < nelem; ++elem) {
386 g_assert_not_reached ();
392 memcpy (dest, val, len * nelem);
397 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
401 guint32 idx = 0, len;
403 len = str->length * 2;
404 mono_metadata_encode_value (len, b, &b);
405 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
407 char *swapped = g_malloc (2 * mono_string_length (str));
408 const char *p = (const char*)mono_string_chars (str);
410 swap_with_size (swapped, p, 2, mono_string_length (str));
411 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
415 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
420 /* modified version needed to handle building corlib */
422 my_mono_class_from_mono_type (MonoType *type) {
423 switch (type->type) {
424 case MONO_TYPE_ARRAY:
426 case MONO_TYPE_SZARRAY:
427 case MONO_TYPE_GENERICINST:
428 return mono_class_from_mono_type (type);
431 g_assert (type->data.generic_param->pklass);
432 return type->data.generic_param->pklass;
434 /* should be always valid when we reach this case... */
435 return type->data.klass;
440 default_class_from_mono_type (MonoType *type)
442 switch (type->type) {
443 case MONO_TYPE_OBJECT:
444 return mono_defaults.object_class;
446 return mono_defaults.void_class;
447 case MONO_TYPE_BOOLEAN:
448 return mono_defaults.boolean_class;
450 return mono_defaults.char_class;
452 return mono_defaults.sbyte_class;
454 return mono_defaults.byte_class;
456 return mono_defaults.int16_class;
458 return mono_defaults.uint16_class;
460 return mono_defaults.int32_class;
462 return mono_defaults.uint32_class;
464 return mono_defaults.int_class;
466 return mono_defaults.uint_class;
468 return mono_defaults.int64_class;
470 return mono_defaults.uint64_class;
472 return mono_defaults.single_class;
474 return mono_defaults.double_class;
475 case MONO_TYPE_STRING:
476 return mono_defaults.string_class;
478 g_warning ("implement me 0x%02x\n", type->type);
479 g_assert_not_reached ();
486 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char *p, char **endbuf)
491 g_assert_not_reached ();
495 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
496 encode_type (assembly, &gclass->container_class->byval_arg, p, &p);
497 mono_metadata_encode_value (gclass->inst->type_argc, p, &p);
498 for (i = 0; i < gclass->inst->type_argc; ++i)
499 encode_type (assembly, gclass->inst->type_argv [i], p, &p);
505 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
508 g_assert_not_reached ();
513 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
517 case MONO_TYPE_BOOLEAN:
531 case MONO_TYPE_STRING:
532 case MONO_TYPE_OBJECT:
533 case MONO_TYPE_TYPEDBYREF:
534 mono_metadata_encode_value (type->type, p, &p);
537 mono_metadata_encode_value (type->type, p, &p);
538 encode_type (assembly, type->data.type, p, &p);
540 case MONO_TYPE_SZARRAY:
541 mono_metadata_encode_value (type->type, p, &p);
542 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
544 case MONO_TYPE_VALUETYPE:
545 case MONO_TYPE_CLASS: {
546 MonoClass *k = mono_class_from_mono_type (type);
548 * Make sure we use the correct type.
550 mono_metadata_encode_value (k->byval_arg.type, p, &p);
552 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
553 * otherwise two typerefs could point to the same type, leading to
554 * verification errors.
556 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
559 case MONO_TYPE_ARRAY:
560 mono_metadata_encode_value (type->type, p, &p);
561 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
562 mono_metadata_encode_value (type->data.array->rank, p, &p);
563 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
564 mono_metadata_encode_value (0, p, &p);
566 case MONO_TYPE_GENERICINST:
567 encode_generic_class (assembly, type->data.generic_class, p, &p);
571 mono_metadata_encode_value (type->type, p, &p);
572 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
575 g_error ("need to encode type %x", type->type);
581 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
584 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
588 encode_type (assembly, type->type, p, endbuf);
592 g_assert_not_reached ();
597 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
602 for (i = 0; i < mono_array_length (modreq); ++i) {
603 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
604 *p = MONO_TYPE_CMOD_REQD;
606 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
610 for (i = 0; i < mono_array_length (modopt); ++i) {
611 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
612 *p = MONO_TYPE_CMOD_OPT;
614 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
621 generic_class_get_signature_size (MonoGenericClass *gclass)
627 g_assert_not_reached ();
630 size += 1 + type_get_signature_size (&gclass->container_class->byval_arg);
632 for (i = 0; i < gclass->inst->type_argc; ++i)
633 size += type_get_signature_size (gclass->inst->type_argv [i]);
639 type_get_signature_size (MonoType *type)
644 g_assert_not_reached ();
652 case MONO_TYPE_BOOLEAN:
666 case MONO_TYPE_STRING:
667 case MONO_TYPE_OBJECT:
668 case MONO_TYPE_TYPEDBYREF:
671 return size + 1 + type_get_signature_size (type->data.type);
672 case MONO_TYPE_SZARRAY:
673 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
674 case MONO_TYPE_VALUETYPE:
675 case MONO_TYPE_CLASS:
677 case MONO_TYPE_ARRAY:
678 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
679 case MONO_TYPE_GENERICINST:
680 return size + generic_class_get_signature_size (type->data.generic_class);
685 g_error ("need to encode type %x", type->type);
691 method_get_signature_size (MonoMethodSignature *sig)
696 size = type_get_signature_size (sig->ret);
697 for (i = 0; i < sig->param_count; i++)
698 size += type_get_signature_size (sig->params [i]);
700 if (sig->generic_param_count)
702 if (sig->sentinelpos >= 0)
709 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
714 guint32 nparams = sig->param_count;
715 guint32 size = 11 + method_get_signature_size (sig);
723 p = buf = g_malloc (size);
725 * FIXME: vararg, explicit_this, differenc call_conv values...
727 *p = sig->call_convention;
729 *p |= 0x20; /* hasthis */
730 if (sig->generic_param_count)
731 *p |= 0x10; /* generic */
733 if (sig->generic_param_count)
734 mono_metadata_encode_value (sig->generic_param_count, p, &p);
735 mono_metadata_encode_value (nparams, p, &p);
736 encode_type (assembly, sig->ret, p, &p);
737 for (i = 0; i < nparams; ++i) {
738 if (i == sig->sentinelpos)
739 *p++ = MONO_TYPE_SENTINEL;
740 encode_type (assembly, sig->params [i], p, &p);
743 g_assert (p - buf < size);
744 mono_metadata_encode_value (p-buf, b, &b);
745 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
751 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
754 * FIXME: reuse code from method_encode_signature().
759 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
760 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
761 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
762 guint32 size = 41 + nparams * 40 + notypes * 40;
767 p = buf = g_malloc (size);
768 /* LAMESPEC: all the call conv spec is foobared */
769 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
770 if (mb->call_conv & 2)
771 *p |= 0x5; /* vararg */
772 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
773 *p |= 0x20; /* hasthis */
775 *p |= 0x10; /* generic */
778 mono_metadata_encode_value (ngparams, p, &p);
779 mono_metadata_encode_value (nparams + notypes, p, &p);
780 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
781 encode_reflection_type (assembly, mb->rtype, p, &p);
782 for (i = 0; i < nparams; ++i) {
783 MonoArray *modreq = NULL;
784 MonoArray *modopt = NULL;
785 MonoReflectionType *pt;
787 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
788 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
789 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
790 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
791 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
792 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
793 encode_reflection_type (assembly, pt, p, &p);
796 *p++ = MONO_TYPE_SENTINEL;
797 for (i = 0; i < notypes; ++i) {
798 MonoReflectionType *pt;
800 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
801 encode_reflection_type (assembly, pt, p, &p);
805 g_assert (p - buf < size);
806 mono_metadata_encode_value (p-buf, b, &b);
807 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
813 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
815 MonoDynamicTable *table;
818 guint32 idx, sig_idx, size;
819 guint nl = mono_array_length (ilgen->locals);
826 p = buf = g_malloc (size);
827 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
828 idx = table->next_idx ++;
830 alloc_table (table, table->rows);
831 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
833 mono_metadata_encode_value (0x07, p, &p);
834 mono_metadata_encode_value (nl, p, &p);
835 for (i = 0; i < nl; ++i) {
836 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
839 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
841 encode_reflection_type (assembly, lb->type, p, &p);
843 g_assert (p - buf < size);
844 mono_metadata_encode_value (p-buf, b, &b);
845 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
848 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
854 method_count_clauses (MonoReflectionILGen *ilgen)
856 guint32 num_clauses = 0;
859 MonoILExceptionInfo *ex_info;
860 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
861 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
862 if (ex_info->handlers)
863 num_clauses += mono_array_length (ex_info->handlers);
871 static MonoExceptionClause*
872 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
874 MonoExceptionClause *clauses;
875 MonoExceptionClause *clause;
876 MonoILExceptionInfo *ex_info;
877 MonoILExceptionBlock *ex_block;
878 guint32 finally_start;
879 int i, j, clause_index;;
881 clauses = g_new0 (MonoExceptionClause, num_clauses);
884 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
885 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
886 finally_start = ex_info->start + ex_info->len;
887 if (!ex_info->handlers)
889 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
890 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
891 clause = &(clauses [clause_index]);
893 clause->flags = ex_block->type;
894 clause->try_offset = ex_info->start;
896 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
897 clause->try_len = finally_start - ex_info->start;
899 clause->try_len = ex_info->len;
900 clause->handler_offset = ex_block->start;
901 clause->handler_len = ex_block->len;
902 if (ex_block->extype) {
903 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
905 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
906 clause->data.filter_offset = ex_block->filter_offset;
908 clause->data.filter_offset = 0;
910 finally_start = ex_block->start + ex_block->len;
920 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
926 gint32 num_locals = 0;
927 gint32 num_exception = 0;
930 char fat_header [12];
933 guint32 local_sig = 0;
934 guint32 header_size = 12;
937 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
938 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
942 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
944 code = mb->ilgen->code;
945 code_size = mb->ilgen->code_len;
946 max_stack = mb->ilgen->max_stack;
947 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
948 if (mb->ilgen->ex_handlers)
949 num_exception = method_count_clauses (mb->ilgen);
953 char *name = mono_string_to_utf8 (mb->name);
954 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
955 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
958 mono_raise_exception (exception);
961 code_size = mono_array_length (code);
962 max_stack = 8; /* we probably need to run a verifier on the code... */
965 stream_data_align (&assembly->code);
967 /* check for exceptions, maxstack, locals */
968 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
970 if (code_size < 64 && !(code_size & 1)) {
971 flags = (code_size << 2) | 0x2;
972 } else if (code_size < 32 && (code_size & 1)) {
973 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
977 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
978 /* add to the fixup todo list */
979 if (mb->ilgen && mb->ilgen->num_token_fixups)
980 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
981 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
982 return assembly->text_rva + idx;
986 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
988 * FIXME: need to set also the header size in fat_flags.
989 * (and more sects and init locals flags)
993 fat_flags |= METHOD_HEADER_MORE_SECTS;
995 fat_flags |= METHOD_HEADER_INIT_LOCALS;
996 fat_header [0] = fat_flags;
997 fat_header [1] = (header_size / 4 ) << 4;
998 short_value = GUINT16_TO_LE (max_stack);
999 memcpy (fat_header + 2, &short_value, 2);
1000 int_value = GUINT32_TO_LE (code_size);
1001 memcpy (fat_header + 4, &int_value, 4);
1002 int_value = GUINT32_TO_LE (local_sig);
1003 memcpy (fat_header + 8, &int_value, 4);
1004 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1005 /* add to the fixup todo list */
1006 if (mb->ilgen && mb->ilgen->num_token_fixups)
1007 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1009 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1010 if (num_exception) {
1011 unsigned char sheader [4];
1012 MonoILExceptionInfo * ex_info;
1013 MonoILExceptionBlock * ex_block;
1016 stream_data_align (&assembly->code);
1017 /* always use fat format for now */
1018 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1019 num_exception *= 6 * sizeof (guint32);
1020 num_exception += 4; /* include the size of the header */
1021 sheader [1] = num_exception & 0xff;
1022 sheader [2] = (num_exception >> 8) & 0xff;
1023 sheader [3] = (num_exception >> 16) & 0xff;
1024 mono_image_add_stream_data (&assembly->code, sheader, 4);
1025 /* fat header, so we are already aligned */
1027 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1028 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1029 if (ex_info->handlers) {
1030 int finally_start = ex_info->start + ex_info->len;
1031 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1033 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1035 val = GUINT32_TO_LE (ex_block->type);
1036 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1038 val = GUINT32_TO_LE (ex_info->start);
1039 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1040 /* need fault, too, probably */
1041 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1042 val = GUINT32_TO_LE (finally_start - ex_info->start);
1044 val = GUINT32_TO_LE (ex_info->len);
1045 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1046 /* handler offset */
1047 val = GUINT32_TO_LE (ex_block->start);
1048 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1050 val = GUINT32_TO_LE (ex_block->len);
1051 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1052 finally_start = ex_block->start + ex_block->len;
1053 if (ex_block->extype) {
1054 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1056 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1057 val = ex_block->filter_offset;
1061 val = GUINT32_TO_LE (val);
1062 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1063 /*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",
1064 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);*/
1067 g_error ("No clauses for ex info block %d", i);
1071 return assembly->text_rva + idx;
1075 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1078 MonoDynamicTable *table;
1081 table = &assembly->tables [table_idx];
1083 g_assert (col < table->columns);
1085 values = table->values + table->columns;
1086 for (i = 1; i <= table->rows; ++i) {
1087 if (values [col] == token)
1089 values += table->columns;
1094 static GHashTable *dynamic_custom_attrs = NULL;
1097 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1099 /* FIXME: Need to do more checks */
1100 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1101 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1103 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1110 static MonoCustomAttrInfo*
1111 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1113 int i, index, count, not_visible;
1114 MonoCustomAttrInfo *ainfo;
1115 MonoReflectionCustomAttr *cattr;
1119 /* FIXME: check in assembly the Run flag is set */
1121 count = mono_array_length (cattrs);
1123 /* Skip nonpublic attributes since MS.NET seems to do the same */
1124 /* FIXME: This needs to be done more globally */
1126 for (i = 0; i < count; ++i) {
1127 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1128 if (!custom_attr_visible (image, cattr))
1131 count -= not_visible;
1133 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1135 ainfo->image = image;
1136 ainfo->num_attrs = count;
1138 for (i = 0; i < count; ++i) {
1139 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1140 if (custom_attr_visible (image, cattr)) {
1141 ainfo->attrs [index].ctor = cattr->ctor->method;
1142 /* FIXME: might want to memdup the data here */
1143 ainfo->attrs [index].data = mono_array_addr (cattr->data, char, 0);
1144 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1153 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1155 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1160 if (!dynamic_custom_attrs)
1161 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1163 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1164 ainfo->cached = TRUE;
1168 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1175 * idx is the table index of the object
1176 * type is one of MONO_CUSTOM_ATTR_*
1179 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1181 MonoDynamicTable *table;
1182 MonoReflectionCustomAttr *cattr;
1184 guint32 count, i, token;
1186 char *p = blob_size;
1188 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1191 count = mono_array_length (cattrs);
1192 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1193 table->rows += count;
1194 alloc_table (table, table->rows);
1195 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1196 idx <<= MONO_CUSTOM_ATTR_BITS;
1198 for (i = 0; i < count; ++i) {
1199 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1200 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1201 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1202 type = mono_metadata_token_index (token);
1203 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1204 switch (mono_metadata_token_table (token)) {
1205 case MONO_TABLE_METHOD:
1206 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1208 case MONO_TABLE_MEMBERREF:
1209 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1212 g_warning ("got wrong token in custom attr");
1215 values [MONO_CUSTOM_ATTR_TYPE] = type;
1217 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1218 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1219 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1220 values += MONO_CUSTOM_ATTR_SIZE;
1226 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1228 MonoDynamicTable *table;
1230 guint32 count, i, idx;
1231 MonoReflectionPermissionSet *perm;
1236 count = mono_array_length (permissions);
1237 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1238 table->rows += count;
1239 alloc_table (table, table->rows);
1241 for (i = 0; i < mono_array_length (permissions); ++i) {
1242 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1244 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1246 idx = mono_metadata_token_index (parent_token);
1247 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1248 switch (mono_metadata_token_table (parent_token)) {
1249 case MONO_TABLE_TYPEDEF:
1250 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1252 case MONO_TABLE_METHOD:
1253 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1255 case MONO_TABLE_ASSEMBLY:
1256 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1259 g_assert_not_reached ();
1262 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1263 values [MONO_DECL_SECURITY_PARENT] = idx;
1264 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1271 * Fill in the MethodDef and ParamDef tables for a method.
1272 * This is used for both normal methods and constructors.
1275 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1277 MonoDynamicTable *table;
1281 /* room in this table is already allocated */
1282 table = &assembly->tables [MONO_TABLE_METHOD];
1283 *mb->table_idx = table->next_idx ++;
1284 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1285 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1286 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1287 values [MONO_METHOD_FLAGS] = mb->attrs;
1288 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1289 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1290 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1292 table = &assembly->tables [MONO_TABLE_PARAM];
1293 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1295 mono_image_add_decl_security (assembly,
1296 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1299 MonoDynamicTable *mtable;
1302 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1303 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1306 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1307 if (mono_array_get (mb->pinfo, gpointer, i))
1310 table->rows += count;
1311 alloc_table (table, table->rows);
1312 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1313 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1314 MonoReflectionParamBuilder *pb;
1315 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1316 values [MONO_PARAM_FLAGS] = pb->attrs;
1317 values [MONO_PARAM_SEQUENCE] = i;
1318 if (pb->name != NULL) {
1319 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1321 values [MONO_PARAM_NAME] = 0;
1323 values += MONO_PARAM_SIZE;
1324 if (pb->marshal_info) {
1326 alloc_table (mtable, mtable->rows);
1327 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1328 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1329 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1331 pb->table_idx = table->next_idx++;
1332 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1333 guint32 field_type = 0;
1334 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1336 alloc_table (mtable, mtable->rows);
1337 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1338 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1339 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1340 mvalues [MONO_CONSTANT_TYPE] = field_type;
1341 mvalues [MONO_CONSTANT_PADDING] = 0;
1349 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1351 rmb->ilgen = mb->ilgen;
1352 rmb->rtype = mb->rtype;
1353 rmb->parameters = mb->parameters;
1354 rmb->generic_params = mb->generic_params;
1355 rmb->generic_container = mb->generic_container;
1356 rmb->opt_types = NULL;
1357 rmb->pinfo = mb->pinfo;
1358 rmb->attrs = mb->attrs;
1359 rmb->iattrs = mb->iattrs;
1360 rmb->call_conv = mb->call_conv;
1361 rmb->code = mb->code;
1362 rmb->type = mb->type;
1363 rmb->name = mb->name;
1364 rmb->table_idx = &mb->table_idx;
1365 rmb->init_locals = mb->init_locals;
1366 rmb->return_modreq = mb->return_modreq;
1367 rmb->return_modopt = mb->return_modopt;
1368 rmb->param_modreq = mb->param_modreq;
1369 rmb->param_modopt = mb->param_modopt;
1370 rmb->permissions = mb->permissions;
1371 rmb->mhandle = mb->mhandle;
1376 rmb->charset = mb->charset;
1377 rmb->extra_flags = mb->extra_flags;
1378 rmb->native_cc = mb->native_cc;
1379 rmb->dllentry = mb->dllentry;
1385 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1387 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1389 rmb->ilgen = mb->ilgen;
1390 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1391 rmb->parameters = mb->parameters;
1392 rmb->generic_params = NULL;
1393 rmb->generic_container = NULL;
1394 rmb->opt_types = NULL;
1395 rmb->pinfo = mb->pinfo;
1396 rmb->attrs = mb->attrs;
1397 rmb->iattrs = mb->iattrs;
1398 rmb->call_conv = mb->call_conv;
1400 rmb->type = mb->type;
1401 rmb->name = mono_string_new (mono_domain_get (), name);
1402 rmb->table_idx = &mb->table_idx;
1403 rmb->init_locals = mb->init_locals;
1404 rmb->return_modreq = NULL;
1405 rmb->return_modopt = NULL;
1406 rmb->param_modreq = mb->param_modreq;
1407 rmb->param_modopt = mb->param_modopt;
1408 rmb->permissions = mb->permissions;
1409 rmb->mhandle = mb->mhandle;
1415 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1417 rmb->ilgen = mb->ilgen;
1418 rmb->rtype = mb->rtype;
1419 rmb->parameters = mb->parameters;
1420 rmb->generic_params = NULL;
1421 rmb->generic_container = NULL;
1422 rmb->opt_types = NULL;
1424 rmb->attrs = mb->attrs;
1426 rmb->call_conv = mb->call_conv;
1429 rmb->name = mb->name;
1430 rmb->table_idx = NULL;
1431 rmb->init_locals = mb->init_locals;
1432 rmb->skip_visibility = mb->skip_visibility;
1433 rmb->return_modreq = NULL;
1434 rmb->return_modopt = NULL;
1435 rmb->param_modreq = NULL;
1436 rmb->param_modopt = NULL;
1437 rmb->permissions = NULL;
1438 rmb->mhandle = mb->mhandle;
1444 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1446 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1447 MonoDynamicTable *table;
1451 if (!mb->override_method)
1454 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1456 alloc_table (table, table->rows);
1457 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1458 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1459 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1461 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1462 switch (mono_metadata_token_table (tok)) {
1463 case MONO_TABLE_MEMBERREF:
1464 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1466 case MONO_TABLE_METHOD:
1467 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1470 g_assert_not_reached ();
1472 values [MONO_METHODIMPL_DECLARATION] = tok;
1476 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1478 MonoDynamicTable *table;
1480 ReflectionMethodBuilder rmb;
1483 reflection_methodbuilder_from_method_builder (&rmb, mb);
1485 mono_image_basic_method (&rmb, assembly);
1486 mb->table_idx = *rmb.table_idx;
1488 if (mb->dll) { /* It's a P/Invoke method */
1490 /* map CharSet values to on-disk values */
1491 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1492 int extra_flags = mb->extra_flags;
1493 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1495 alloc_table (table, table->rows);
1496 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1498 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1499 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1501 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1503 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1504 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1505 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1506 table = &assembly->tables [MONO_TABLE_MODULEREF];
1508 alloc_table (table, table->rows);
1509 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1510 values [MONO_IMPLMAP_SCOPE] = table->rows;
1514 if (mb->generic_params) {
1515 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1516 table->rows += mono_array_length (mb->generic_params);
1517 alloc_table (table, table->rows);
1518 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1519 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1521 mono_image_get_generic_param_info (
1522 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1529 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1531 ReflectionMethodBuilder rmb;
1533 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1535 mono_image_basic_method (&rmb, assembly);
1536 mb->table_idx = *rmb.table_idx;
1540 type_get_fully_qualified_name (MonoType *type)
1542 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1546 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1550 klass = my_mono_class_from_mono_type (type);
1552 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1553 ta = klass->image->assembly;
1554 if (ta->dynamic || (ta == ass))
1555 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1557 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1561 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1563 char blob_size [64];
1564 char *b = blob_size;
1569 if (!assembly->save)
1572 p = buf = g_malloc (256);
1574 mono_metadata_encode_value (0x06, p, &p);
1575 /* encode custom attributes before the type */
1576 encode_type (assembly, type, p, &p);
1577 g_assert (p-buf < 256);
1578 mono_metadata_encode_value (p-buf, b, &b);
1579 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1585 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1587 char blob_size [64];
1588 char *b = blob_size;
1593 p = buf = g_malloc (256);
1595 mono_metadata_encode_value (0x06, p, &p);
1596 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1597 /* encode custom attributes before the type */
1598 encode_reflection_type (assembly, fb->type, p, &p);
1599 g_assert (p-buf < 256);
1600 mono_metadata_encode_value (p-buf, b, &b);
1601 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1607 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1608 char blob_size [64];
1609 char *b = blob_size;
1612 guint32 idx = 0, len = 0, dummy = 0;
1614 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1615 guint32 fpa_double [2];
1620 p = buf = g_malloc (64);
1622 *ret_type = MONO_TYPE_CLASS;
1624 box_val = (char*)&dummy;
1626 box_val = ((char*)val) + sizeof (MonoObject);
1627 *ret_type = val->vtable->klass->byval_arg.type;
1630 switch (*ret_type) {
1631 case MONO_TYPE_BOOLEAN:
1636 case MONO_TYPE_CHAR:
1653 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1654 fpa_p = (guint32*)box_val;
1655 fpa_double [0] = fpa_p [1];
1656 fpa_double [1] = fpa_p [0];
1657 box_val = (char*)fpa_double;
1661 case MONO_TYPE_VALUETYPE:
1662 if (val->vtable->klass->enumtype) {
1663 *ret_type = val->vtable->klass->enum_basetype->type;
1666 g_error ("we can't encode valuetypes");
1667 case MONO_TYPE_CLASS:
1669 case MONO_TYPE_STRING: {
1670 MonoString *str = (MonoString*)val;
1671 /* there is no signature */
1672 len = str->length * 2;
1673 mono_metadata_encode_value (len, b, &b);
1674 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1676 char *swapped = g_malloc (2 * mono_string_length (str));
1677 const char *p = (const char*)mono_string_chars (str);
1679 swap_with_size (swapped, p, 2, mono_string_length (str));
1680 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1684 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1691 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1694 /* there is no signature */
1695 mono_metadata_encode_value (len, b, &b);
1696 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1697 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1698 swap_with_size (blob_size, box_val, len, 1);
1699 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1701 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1709 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1710 char blob_size [64];
1711 char *b = blob_size;
1712 char *p, *buf, *str;
1713 guint32 idx, len, bufsize = 256;
1715 p = buf = g_malloc (bufsize);
1717 mono_metadata_encode_value (minfo->type, p, &p);
1719 switch (minfo->type) {
1720 case MONO_NATIVE_BYVALTSTR:
1721 case MONO_NATIVE_BYVALARRAY:
1722 mono_metadata_encode_value (minfo->count, p, &p);
1724 case MONO_NATIVE_LPARRAY:
1725 if (minfo->eltype || minfo->has_size) {
1726 mono_metadata_encode_value (minfo->eltype, p, &p);
1727 if (minfo->has_size) {
1728 if (minfo->param_num != -1)
1729 mono_metadata_encode_value (minfo->param_num, p, &p);
1731 mono_metadata_encode_value (0, p, &p);
1732 if (minfo->count != -1)
1733 mono_metadata_encode_value (minfo->count, p, &p);
1735 mono_metadata_encode_value (0, p, &p);
1737 /* LAMESPEC: ElemMult is undocumented */
1738 if (minfo->param_num != -1)
1739 mono_metadata_encode_value (1, p, &p);
1741 mono_metadata_encode_value (0, p, &p);
1745 case MONO_NATIVE_CUSTOM:
1747 str = mono_string_to_utf8 (minfo->guid);
1749 mono_metadata_encode_value (len, p, &p);
1750 memcpy (p, str, len);
1754 mono_metadata_encode_value (0, p, &p);
1756 /* native type name */
1757 mono_metadata_encode_value (0, p, &p);
1758 /* custom marshaler type name */
1759 if (minfo->marshaltype || minfo->marshaltyperef) {
1760 if (minfo->marshaltyperef)
1761 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1763 str = mono_string_to_utf8 (minfo->marshaltype);
1765 mono_metadata_encode_value (len, p, &p);
1766 if (p + len >= buf + bufsize) {
1769 buf = g_realloc (buf, bufsize);
1772 memcpy (p, str, len);
1776 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1777 mono_metadata_encode_value (0, p, &p);
1779 if (minfo->mcookie) {
1780 str = mono_string_to_utf8 (minfo->mcookie);
1782 mono_metadata_encode_value (len, p, &p);
1783 if (p + len >= buf + bufsize) {
1786 buf = g_realloc (buf, bufsize);
1789 memcpy (p, str, len);
1793 mono_metadata_encode_value (0, p, &p);
1800 mono_metadata_encode_value (len, b, &b);
1801 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1807 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1809 MonoDynamicTable *table;
1812 /* maybe this fixup should be done in the C# code */
1813 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1814 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1815 table = &assembly->tables [MONO_TABLE_FIELD];
1816 fb->table_idx = table->next_idx ++;
1817 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1818 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1819 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1820 values [MONO_FIELD_FLAGS] = fb->attrs;
1821 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1823 if (fb->offset != -1) {
1824 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1826 alloc_table (table, table->rows);
1827 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1828 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1829 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1831 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1832 guint32 field_type = 0;
1833 table = &assembly->tables [MONO_TABLE_CONSTANT];
1835 alloc_table (table, table->rows);
1836 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1837 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1838 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1839 values [MONO_CONSTANT_TYPE] = field_type;
1840 values [MONO_CONSTANT_PADDING] = 0;
1842 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1844 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1846 alloc_table (table, table->rows);
1847 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1848 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1850 * We store it in the code section because it's simpler for now.
1853 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1855 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1856 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1858 if (fb->marshal_info) {
1859 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1861 alloc_table (table, table->rows);
1862 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1863 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1864 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1869 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1873 char *b = blob_size;
1874 guint32 nparams = 0;
1875 MonoReflectionMethodBuilder *mb = fb->get_method;
1876 MonoReflectionMethodBuilder *smb = fb->set_method;
1877 guint32 idx, i, size;
1879 if (mb && mb->parameters)
1880 nparams = mono_array_length (mb->parameters);
1881 if (!mb && smb && smb->parameters)
1882 nparams = mono_array_length (smb->parameters) - 1;
1883 size = 24 + nparams * 10;
1884 buf = p = g_malloc (size);
1887 mono_metadata_encode_value (nparams, p, &p);
1889 encode_reflection_type (assembly, mb->rtype, p, &p);
1890 for (i = 0; i < nparams; ++i) {
1891 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1892 encode_reflection_type (assembly, pt, p, &p);
1894 } else if (smb && smb->parameters) {
1895 /* the property type is the last param */
1896 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1897 for (i = 0; i < nparams; ++i) {
1898 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1899 encode_reflection_type (assembly, pt, p, &p);
1903 encode_reflection_type (assembly, fb->type, p, &p);
1907 g_assert (p - buf < size);
1908 mono_metadata_encode_value (p-buf, b, &b);
1909 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1915 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1917 MonoDynamicTable *table;
1919 guint num_methods = 0;
1923 * we need to set things in the following tables:
1924 * PROPERTYMAP (info already filled in _get_type_info ())
1925 * PROPERTY (rows already preallocated in _get_type_info ())
1926 * METHOD (method info already done with the generic method code)
1929 table = &assembly->tables [MONO_TABLE_PROPERTY];
1930 pb->table_idx = table->next_idx ++;
1931 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1932 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1933 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1934 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1936 /* FIXME: we still don't handle 'other' methods */
1937 if (pb->get_method) num_methods ++;
1938 if (pb->set_method) num_methods ++;
1940 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1941 table->rows += num_methods;
1942 alloc_table (table, table->rows);
1944 if (pb->get_method) {
1945 semaidx = table->next_idx ++;
1946 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1947 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1948 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1949 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1951 if (pb->set_method) {
1952 semaidx = table->next_idx ++;
1953 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1954 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1955 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1956 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1961 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1963 MonoDynamicTable *table;
1965 guint num_methods = 0;
1969 * we need to set things in the following tables:
1970 * EVENTMAP (info already filled in _get_type_info ())
1971 * EVENT (rows already preallocated in _get_type_info ())
1972 * METHOD (method info already done with the generic method code)
1975 table = &assembly->tables [MONO_TABLE_EVENT];
1976 eb->table_idx = table->next_idx ++;
1977 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1978 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1979 values [MONO_EVENT_FLAGS] = eb->attrs;
1980 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1983 * FIXME: we still don't handle 'other' methods
1985 if (eb->add_method) num_methods ++;
1986 if (eb->remove_method) num_methods ++;
1987 if (eb->raise_method) num_methods ++;
1989 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1990 table->rows += num_methods;
1991 alloc_table (table, table->rows);
1993 if (eb->add_method) {
1994 semaidx = table->next_idx ++;
1995 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1996 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1997 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1998 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2000 if (eb->remove_method) {
2001 semaidx = table->next_idx ++;
2002 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2003 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2004 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2005 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2007 if (eb->raise_method) {
2008 semaidx = table->next_idx ++;
2009 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2010 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2011 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2012 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2017 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2019 MonoDynamicTable *table;
2020 guint32 num_constraints, i;
2024 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2025 num_constraints = gparam->iface_constraints ?
2026 mono_array_length (gparam->iface_constraints) : 0;
2027 table->rows += num_constraints;
2028 if (gparam->base_type)
2030 alloc_table (table, table->rows);
2032 if (gparam->base_type) {
2033 table_idx = table->next_idx ++;
2034 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2036 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2037 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2038 assembly, gparam->base_type->type);
2041 for (i = 0; i < num_constraints; i++) {
2042 MonoReflectionType *constraint = mono_array_get (
2043 gparam->iface_constraints, gpointer, i);
2045 table_idx = table->next_idx ++;
2046 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2048 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2049 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2050 assembly, constraint->type);
2055 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2057 GenericParamTableEntry *entry;
2060 * The GenericParam table must be sorted according to the `owner' field.
2061 * We need to do this sorting prior to writing the GenericParamConstraint
2062 * table, since we have to use the final GenericParam table indices there
2063 * and they must also be sorted.
2066 entry = g_new0 (GenericParamTableEntry, 1);
2067 entry->owner = owner;
2069 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2070 MONO_GC_REGISTER_ROOT (entry->gparam);
2072 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2074 g_ptr_array_add (assembly->gen_params, entry);
2078 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2080 MonoDynamicTable *table;
2081 MonoGenericParam *param;
2085 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2086 table_idx = table->next_idx ++;
2087 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2089 param = entry->gparam->type.type->data.generic_param;
2091 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2092 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2093 values [MONO_GENERICPARAM_NUMBER] = param->num;
2094 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2096 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2098 encode_constraints (entry->gparam, table_idx, assembly);
2102 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2104 MonoDynamicTable *table;
2107 guint32 cols [MONO_ASSEMBLY_SIZE];
2111 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2114 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2115 table = &assembly->tables [MONO_TABLE_MODULEREF];
2116 token = table->next_idx ++;
2118 alloc_table (table, table->rows);
2119 values = table->values + token * MONO_MODULEREF_SIZE;
2120 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2122 token <<= MONO_RESOLTION_SCOPE_BITS;
2123 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2124 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2129 if (image->assembly->dynamic)
2131 memset (cols, 0, sizeof (cols));
2133 /* image->assembly->image is the manifest module */
2134 image = image->assembly->image;
2135 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2138 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2139 token = table->next_idx ++;
2141 alloc_table (table, table->rows);
2142 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2143 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2144 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2145 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2146 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2147 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2148 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2149 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2150 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2152 if (strcmp ("", image->assembly->aname.culture)) {
2153 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2154 image->assembly->aname.culture);
2157 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2158 guchar pubtoken [9];
2160 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2161 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2163 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2165 token <<= MONO_RESOLTION_SCOPE_BITS;
2166 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2167 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2172 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2174 MonoDynamicTable *table;
2180 char *b = blob_size;
2182 switch (type->type) {
2183 case MONO_TYPE_FNPTR:
2185 case MONO_TYPE_SZARRAY:
2186 case MONO_TYPE_ARRAY:
2188 case MONO_TYPE_MVAR:
2189 case MONO_TYPE_GENERICINST:
2190 encode_type (assembly, type, p, &p);
2192 case MONO_TYPE_CLASS:
2193 case MONO_TYPE_VALUETYPE: {
2194 MonoClass *k = mono_class_from_mono_type (type);
2195 if (!k || !k->generic_class)
2197 encode_generic_class (assembly, k->generic_class, p, &p);
2204 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2205 if (assembly->save) {
2206 g_assert (p-sig < 128);
2207 mono_metadata_encode_value (p-sig, b, &b);
2208 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2209 alloc_table (table, table->rows + 1);
2210 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2211 values [MONO_TYPESPEC_SIGNATURE] = token;
2214 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2215 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2221 * Despite the name, we handle also TypeSpec (with the above helper).
2224 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2226 MonoDynamicTable *table;
2228 guint32 token, scope, enclosing;
2231 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2234 token = create_typespec (assembly, type);
2237 klass = my_mono_class_from_mono_type (type);
2239 klass = mono_class_from_mono_type (type);
2242 * If it's in the same module and not a generic type parameter:
2244 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2245 (type->type != MONO_TYPE_MVAR)) {
2246 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2247 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2248 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2252 if (klass->nested_in) {
2253 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2254 /* get the typeref idx of the enclosing type */
2255 enclosing >>= MONO_TYPEDEFORREF_BITS;
2256 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2258 scope = resolution_scope_from_image (assembly, klass->image);
2260 table = &assembly->tables [MONO_TABLE_TYPEREF];
2261 if (assembly->save) {
2262 alloc_table (table, table->rows + 1);
2263 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2264 values [MONO_TYPEREF_SCOPE] = scope;
2265 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2266 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2268 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2269 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2271 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2276 * Insert a memberef row into the metadata: the token that point to the memberref
2277 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2278 * mono_image_get_fieldref_token()).
2279 * The sig param is an index to an already built signature.
2282 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2284 MonoDynamicTable *table;
2286 guint32 token, pclass;
2289 parent = mono_image_typedef_or_ref (assembly, type);
2290 switch (parent & MONO_TYPEDEFORREF_MASK) {
2291 case MONO_TYPEDEFORREF_TYPEREF:
2292 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2294 case MONO_TYPEDEFORREF_TYPESPEC:
2295 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2297 case MONO_TYPEDEFORREF_TYPEDEF:
2298 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2301 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2304 /* extract the index */
2305 parent >>= MONO_TYPEDEFORREF_BITS;
2307 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2309 if (assembly->save) {
2310 alloc_table (table, table->rows + 1);
2311 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2312 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2313 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2314 values [MONO_MEMBERREF_SIGNATURE] = sig;
2317 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2324 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2327 MonoMethodSignature *sig;
2329 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2334 * A methodref signature can't contain an unmanaged calling convention.
2336 sig = mono_metadata_signature_dup (mono_method_signature (method));
2337 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2338 sig->call_convention = MONO_CALL_DEFAULT;
2339 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2340 method->name, method_encode_signature (assembly, sig));
2342 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2347 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2348 const gchar *name, guint32 sig)
2350 MonoDynamicTable *table;
2354 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2356 if (assembly->save) {
2357 alloc_table (table, table->rows + 1);
2358 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2359 values [MONO_MEMBERREF_CLASS] = original;
2360 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2361 values [MONO_MEMBERREF_SIGNATURE] = sig;
2364 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2371 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2374 ReflectionMethodBuilder rmb;
2376 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2380 reflection_methodbuilder_from_method_builder (&rmb, mb);
2382 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2383 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2384 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2389 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2392 ReflectionMethodBuilder rmb;
2394 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2398 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2400 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2401 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2402 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2407 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2412 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2415 g_assert (f->field->parent);
2416 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2417 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2418 f->field->name, fieldref_encode_signature (assembly, type));
2419 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2424 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2429 guint32 nparams = gmethod->inst->type_argc;
2430 guint32 size = 10 + nparams * 30;
2433 char *b = blob_size;
2435 if (!assembly->save)
2438 p = buf = g_malloc (size);
2440 * FIXME: vararg, explicit_this, differenc call_conv values...
2442 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2443 mono_metadata_encode_value (nparams, p, &p);
2445 for (i = 0; i < nparams; i++)
2446 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2449 g_assert (p - buf < size);
2450 mono_metadata_encode_value (p-buf, b, &b);
2451 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2457 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2459 MonoDynamicTable *table;
2461 guint32 token, mtoken = 0, sig;
2462 MonoMethodInflated *imethod;
2463 MonoMethod *declaring;
2465 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2467 g_assert (method->is_inflated);
2468 method = mono_get_inflated_method (method);
2469 imethod = (MonoMethodInflated *) method;
2470 declaring = imethod->declaring;
2472 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2473 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2475 if (!mono_method_signature (declaring)->generic_param_count)
2478 switch (mono_metadata_token_table (mtoken)) {
2479 case MONO_TABLE_MEMBERREF:
2480 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2482 case MONO_TABLE_METHOD:
2483 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2486 g_assert_not_reached ();
2489 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2491 if (assembly->save) {
2492 alloc_table (table, table->rows + 1);
2493 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2494 values [MONO_METHODSPEC_METHOD] = mtoken;
2495 values [MONO_METHODSPEC_SIGNATURE] = sig;
2498 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2505 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2507 MonoMethodInflated *imethod;
2508 MonoMethod *inflated;
2511 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2515 g_assert (method->is_inflated);
2516 inflated = mono_get_inflated_method (method);
2517 imethod = (MonoMethodInflated *) inflated;
2519 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2520 token = method_encode_methodspec (assembly, inflated);
2522 guint32 sig = method_encode_signature (
2523 assembly, mono_method_signature (imethod->declaring));
2524 token = mono_image_get_memberref_token (
2525 assembly, &inflated->klass->byval_arg, inflated->name, sig);
2528 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2533 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2535 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2538 m = mono_get_inflated_method (m);
2540 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2541 token = mono_image_get_memberref_token (
2542 assembly, &m->klass->byval_arg, m->name, sig);
2548 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2550 MonoDynamicTable *table;
2557 char *b = blob_size;
2561 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2562 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2563 * Because of this, we must not insert it into the `typeref' hash table.
2566 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2570 g_assert (tb->generic_params);
2571 klass = mono_class_from_mono_type (tb->type.type);
2573 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2574 encode_type (assembly, &klass->byval_arg, p, &p);
2576 count = mono_array_length (tb->generic_params);
2577 mono_metadata_encode_value (count, p, &p);
2578 for (i = 0; i < count; i++) {
2579 MonoReflectionGenericParam *gparam;
2581 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2583 encode_type (assembly, gparam->type.type, p, &p);
2586 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2587 g_assert (p-sig < 128);
2589 if (assembly->save) {
2590 mono_metadata_encode_value (p-sig, b, &b);
2591 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2592 alloc_table (table, table->rows + 1);
2593 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2594 values [MONO_TYPESPEC_SIGNATURE] = token;
2597 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2598 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2604 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2606 MonoDynamicTable *table;
2609 guint32 token, pclass, parent, sig;
2612 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2616 klass = mono_class_from_mono_type (fb->typeb->type);
2617 name = mono_string_to_utf8 (fb->name);
2619 sig = fieldref_encode_signature (assembly, fb->type->type);
2621 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2622 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2624 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2625 parent >>= MONO_TYPEDEFORREF_BITS;
2627 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2629 if (assembly->save) {
2630 alloc_table (table, table->rows + 1);
2631 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2632 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2633 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2634 values [MONO_MEMBERREF_SIGNATURE] = sig;
2637 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2639 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2644 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2652 char *b = blob_size;
2654 if (!assembly->save)
2658 g_assert (helper->type == 2);
2660 if (helper->arguments)
2661 nargs = mono_array_length (helper->arguments);
2665 size = 10 + (nargs * 10);
2667 p = buf = g_malloc (size);
2669 /* Encode calling convention */
2670 /* Change Any to Standard */
2671 if ((helper->call_conv & 0x03) == 0x03)
2672 helper->call_conv = 0x01;
2673 /* explicit_this implies has_this */
2674 if (helper->call_conv & 0x40)
2675 helper->call_conv &= 0x20;
2677 if (helper->call_conv == 0) { /* Unmanaged */
2678 *p = helper->unmanaged_call_conv - 1;
2681 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2682 if (helper->call_conv & 0x02) /* varargs */
2687 mono_metadata_encode_value (nargs, p, &p);
2688 encode_reflection_type (assembly, helper->return_type, p, &p);
2689 for (i = 0; i < nargs; ++i) {
2690 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2691 encode_reflection_type (assembly, pt, p, &p);
2694 g_assert (p - buf < size);
2695 mono_metadata_encode_value (p-buf, b, &b);
2696 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2703 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2706 MonoDynamicTable *table;
2709 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2710 idx = table->next_idx ++;
2712 alloc_table (table, table->rows);
2713 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2715 values [MONO_STAND_ALONE_SIGNATURE] =
2716 mono_reflection_encode_sighelper (assembly, helper);
2722 reflection_cc_to_file (int call_conv) {
2723 switch (call_conv & 0x3) {
2725 case 1: return MONO_CALL_DEFAULT;
2726 case 2: return MONO_CALL_VARARG;
2728 g_assert_not_reached ();
2735 MonoMethodSignature *sig;
2741 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2746 MonoMethodSignature *sig;
2749 name = mono_string_to_utf8 (m->name);
2750 nparams = mono_array_length (m->parameters);
2751 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2753 sig->sentinelpos = -1;
2754 sig->call_convention = reflection_cc_to_file (m->call_conv);
2755 sig->param_count = nparams;
2756 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2757 for (i = 0; i < nparams; ++i) {
2758 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2759 sig->params [i] = t->type;
2762 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2764 if (strcmp (name, am->name) == 0 &&
2765 mono_metadata_type_equal (am->parent, m->parent->type) &&
2766 mono_metadata_signature_equal (am->sig, sig)) {
2769 m->table_idx = am->token & 0xffffff;
2773 am = g_new0 (ArrayMethod, 1);
2776 am->parent = m->parent->type;
2777 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2778 method_encode_signature (assembly, sig));
2779 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2780 m->table_idx = am->token & 0xffffff;
2785 * Insert into the metadata tables all the info about the TypeBuilder tb.
2786 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2789 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2791 MonoDynamicTable *table;
2793 int i, is_object = 0, is_system = 0;
2796 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2797 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2798 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2799 n = mono_string_to_utf8 (tb->name);
2800 if (strcmp (n, "Object") == 0)
2802 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2804 n = mono_string_to_utf8 (tb->nspace);
2805 if (strcmp (n, "System") == 0)
2807 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2809 if (tb->parent && !(is_system && is_object) &&
2810 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2811 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2813 values [MONO_TYPEDEF_EXTENDS] = 0;
2815 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2816 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2819 * if we have explicitlayout or sequentiallayouts, output data in the
2820 * ClassLayout table.
2822 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2823 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2824 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2826 alloc_table (table, table->rows);
2827 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2828 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2829 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2830 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2833 /* handle interfaces */
2834 if (tb->interfaces) {
2835 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2837 table->rows += mono_array_length (tb->interfaces);
2838 alloc_table (table, table->rows);
2839 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2840 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2841 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2842 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2843 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2844 values += MONO_INTERFACEIMPL_SIZE;
2850 table = &assembly->tables [MONO_TABLE_FIELD];
2851 table->rows += tb->num_fields;
2852 alloc_table (table, table->rows);
2853 for (i = 0; i < tb->num_fields; ++i)
2854 mono_image_get_field_info (
2855 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2858 /* handle constructors */
2860 table = &assembly->tables [MONO_TABLE_METHOD];
2861 table->rows += mono_array_length (tb->ctors);
2862 alloc_table (table, table->rows);
2863 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2864 mono_image_get_ctor_info (domain,
2865 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2868 /* handle methods */
2870 table = &assembly->tables [MONO_TABLE_METHOD];
2871 table->rows += tb->num_methods;
2872 alloc_table (table, table->rows);
2873 for (i = 0; i < tb->num_methods; ++i)
2874 mono_image_get_method_info (
2875 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2878 /* Do the same with properties etc.. */
2879 if (tb->events && mono_array_length (tb->events)) {
2880 table = &assembly->tables [MONO_TABLE_EVENT];
2881 table->rows += mono_array_length (tb->events);
2882 alloc_table (table, table->rows);
2883 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2885 alloc_table (table, table->rows);
2886 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2887 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2888 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2889 for (i = 0; i < mono_array_length (tb->events); ++i)
2890 mono_image_get_event_info (
2891 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2893 if (tb->properties && mono_array_length (tb->properties)) {
2894 table = &assembly->tables [MONO_TABLE_PROPERTY];
2895 table->rows += mono_array_length (tb->properties);
2896 alloc_table (table, table->rows);
2897 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2899 alloc_table (table, table->rows);
2900 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2901 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2902 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2903 for (i = 0; i < mono_array_length (tb->properties); ++i)
2904 mono_image_get_property_info (
2905 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2908 /* handle generic parameters */
2909 if (tb->generic_params) {
2910 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2911 table->rows += mono_array_length (tb->generic_params);
2912 alloc_table (table, table->rows);
2913 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2914 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2916 mono_image_get_generic_param_info (
2917 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2921 mono_image_add_decl_security (assembly,
2922 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2925 MonoDynamicTable *ntable;
2927 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2928 ntable->rows += mono_array_length (tb->subtypes);
2929 alloc_table (ntable, ntable->rows);
2930 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2932 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2933 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2935 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2936 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2937 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2938 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2939 mono_string_to_utf8 (tb->name), tb->table_idx,
2940 ntable->next_idx, ntable->rows);*/
2941 values += MONO_NESTED_CLASS_SIZE;
2948 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2952 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2954 if (!type->subtypes)
2957 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2958 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2959 collect_types (types, subtype);
2964 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2966 if ((*type1)->table_idx < (*type2)->table_idx)
2969 if ((*type1)->table_idx > (*type2)->table_idx)
2976 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2981 for (i = 0; i < mono_array_length (pinfo); ++i) {
2982 MonoReflectionParamBuilder *pb;
2983 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2986 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2991 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2994 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2996 for (i = 0; i < tb->num_fields; ++i) {
2997 MonoReflectionFieldBuilder* fb;
2998 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2999 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3003 for (i = 0; i < mono_array_length (tb->events); ++i) {
3004 MonoReflectionEventBuilder* eb;
3005 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3006 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3009 if (tb->properties) {
3010 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3011 MonoReflectionPropertyBuilder* pb;
3012 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3013 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3017 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3018 MonoReflectionCtorBuilder* cb;
3019 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3020 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3021 params_add_cattrs (assembly, cb->pinfo);
3026 for (i = 0; i < tb->num_methods; ++i) {
3027 MonoReflectionMethodBuilder* mb;
3028 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3029 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3030 params_add_cattrs (assembly, mb->pinfo);
3035 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3036 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3041 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3045 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3047 if (moduleb->global_methods) {
3048 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3049 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3050 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3051 params_add_cattrs (assembly, mb->pinfo);
3055 if (moduleb->global_fields) {
3056 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3057 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3058 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3062 if (moduleb->types) {
3063 for (i = 0; i < moduleb->num_types; ++i)
3064 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3069 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3071 MonoDynamicTable *table;
3075 char *b = blob_size;
3078 table = &assembly->tables [MONO_TABLE_FILE];
3080 alloc_table (table, table->rows);
3081 values = table->values + table->next_idx * MONO_FILE_SIZE;
3082 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3083 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3084 if (module->image->dynamic) {
3085 /* This depends on the fact that the main module is emitted last */
3086 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3087 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3090 path = g_strdup (module->image->name);
3092 mono_sha1_get_digest_from_file (path, hash);
3095 mono_metadata_encode_value (20, b, &b);
3096 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3097 mono_image_add_stream_data (&assembly->blob, hash, 20);
3102 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3104 MonoDynamicTable *table;
3107 table = &assembly->tables [MONO_TABLE_MODULE];
3108 mb->table_idx = table->next_idx ++;
3109 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3110 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3113 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3114 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3115 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3116 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3120 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3121 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3123 MonoDynamicTable *table;
3127 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3128 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3131 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3133 alloc_table (table, table->rows);
3134 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3136 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3137 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3138 if (klass->nested_in)
3139 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3141 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3142 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3143 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3145 res = table->next_idx;
3149 /* Emit nested types */
3150 if (klass->nested_classes) {
3153 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3154 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3161 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3162 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3167 klass = mono_class_from_mono_type (tb->type.type);
3169 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3171 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3172 parent_index, assembly);
3176 * We need to do this ourselves since klass->nested_classes is not set up.
3179 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3180 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3185 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3186 guint32 module_index, MonoDynamicImage *assembly)
3188 MonoImage *image = module->image;
3192 t = &image->tables [MONO_TABLE_TYPEDEF];
3194 for (i = 0; i < t->rows; ++i) {
3195 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3197 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3198 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3203 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3205 MonoDynamicTable *table;
3211 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3213 if (assemblyb->type_forwarders) {
3214 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3215 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3221 klass = mono_class_from_mono_type (t->type);
3223 scope = resolution_scope_from_image (assembly, klass->image);
3224 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3225 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3228 alloc_table (table, table->rows);
3229 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3231 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3232 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3233 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3234 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3235 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3240 #define align_pointer(base,p)\
3242 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3244 (p) += 4 - (__diff & 3);\
3248 compare_constants (const void *a, const void *b)
3250 const guint32 *a_values = a;
3251 const guint32 *b_values = b;
3252 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3256 compare_semantics (const void *a, const void *b)
3258 const guint32 *a_values = a;
3259 const guint32 *b_values = b;
3260 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3263 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3267 compare_custom_attrs (const void *a, const void *b)
3269 const guint32 *a_values = a;
3270 const guint32 *b_values = b;
3272 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3276 compare_field_marshal (const void *a, const void *b)
3278 const guint32 *a_values = a;
3279 const guint32 *b_values = b;
3281 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3285 compare_nested (const void *a, const void *b)
3287 const guint32 *a_values = a;
3288 const guint32 *b_values = b;
3290 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3294 compare_genericparam (const void *a, const void *b)
3296 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3297 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3299 if ((*b_entry)->owner == (*a_entry)->owner)
3301 (*a_entry)->gparam->type.type->data.generic_param->num -
3302 (*b_entry)->gparam->type.type->data.generic_param->num;
3304 return (*a_entry)->owner - (*b_entry)->owner;
3308 compare_declsecurity_attrs (const void *a, const void *b)
3310 const guint32 *a_values = a;
3311 const guint32 *b_values = b;
3313 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3317 pad_heap (MonoDynamicStream *sh)
3319 if (sh->index & 3) {
3320 int sz = 4 - (sh->index & 3);
3321 memset (sh->data + sh->index, 0, sz);
3328 MonoDynamicStream *stream;
3332 * build_compressed_metadata() fills in the blob of data that represents the
3333 * raw metadata as it will be saved in the PE file. The five streams are output
3334 * and the metadata tables are comnpressed from the guint32 array representation,
3335 * to the compressed on-disk format.
3338 build_compressed_metadata (MonoDynamicImage *assembly)
3340 MonoDynamicTable *table;
3342 guint64 valid_mask = 0;
3343 guint64 sorted_mask;
3344 guint32 heapt_size = 0;
3345 guint32 meta_size = 256; /* allow for header and other stuff */
3346 guint32 table_offset;
3347 guint32 ntables = 0;
3353 struct StreamDesc stream_desc [5];
3355 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3356 for (i = 0; i < assembly->gen_params->len; i++){
3357 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3358 write_generic_param_entry (assembly, entry);
3361 stream_desc [0].name = "#~";
3362 stream_desc [0].stream = &assembly->tstream;
3363 stream_desc [1].name = "#Strings";
3364 stream_desc [1].stream = &assembly->sheap;
3365 stream_desc [2].name = "#US";
3366 stream_desc [2].stream = &assembly->us;
3367 stream_desc [3].name = "#Blob";
3368 stream_desc [3].stream = &assembly->blob;
3369 stream_desc [4].name = "#GUID";
3370 stream_desc [4].stream = &assembly->guid;
3372 /* tables that are sorted */
3373 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3374 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3375 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3376 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3377 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3378 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3380 /* Compute table sizes */
3381 /* the MonoImage has already been created in mono_image_basic_init() */
3382 meta = &assembly->image;
3384 /* sizes should be multiple of 4 */
3385 pad_heap (&assembly->blob);
3386 pad_heap (&assembly->guid);
3387 pad_heap (&assembly->sheap);
3388 pad_heap (&assembly->us);
3390 /* Setup the info used by compute_sizes () */
3391 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3392 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3393 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3395 meta_size += assembly->blob.index;
3396 meta_size += assembly->guid.index;
3397 meta_size += assembly->sheap.index;
3398 meta_size += assembly->us.index;
3400 for (i=0; i < MONO_TABLE_NUM; ++i)
3401 meta->tables [i].rows = assembly->tables [i].rows;
3403 for (i = 0; i < MONO_TABLE_NUM; i++){
3404 if (meta->tables [i].rows == 0)
3406 valid_mask |= (guint64)1 << i;
3408 meta->tables [i].row_size = mono_metadata_compute_size (
3409 meta, i, &meta->tables [i].size_bitfield);
3410 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3412 heapt_size += 24; /* #~ header size */
3413 heapt_size += ntables * 4;
3414 /* make multiple of 4 */
3417 meta_size += heapt_size;
3418 meta->raw_metadata = g_malloc0 (meta_size);
3419 p = meta->raw_metadata;
3420 /* the metadata signature */
3421 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3422 /* version numbers and 4 bytes reserved */
3423 int16val = (guint16*)p;
3424 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3425 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3427 /* version string */
3428 int32val = (guint32*)p;
3429 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3431 memcpy (p, meta->version, strlen (meta->version));
3432 p += GUINT32_FROM_LE (*int32val);
3433 align_pointer (meta->raw_metadata, p);
3434 int16val = (guint16*)p;
3435 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3436 *int16val = GUINT16_TO_LE (5); /* number of streams */
3440 * write the stream info.
3442 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3443 table_offset += 3; table_offset &= ~3;
3445 assembly->tstream.index = heapt_size;
3446 for (i = 0; i < 5; ++i) {
3447 int32val = (guint32*)p;
3448 stream_desc [i].stream->offset = table_offset;
3449 *int32val++ = GUINT32_TO_LE (table_offset);
3450 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3451 table_offset += GUINT32_FROM_LE (*int32val);
3452 table_offset += 3; table_offset &= ~3;
3454 strcpy (p, stream_desc [i].name);
3455 p += strlen (stream_desc [i].name) + 1;
3456 align_pointer (meta->raw_metadata, p);
3459 * now copy the data, the table stream header and contents goes first.
3461 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3462 p = meta->raw_metadata + assembly->tstream.offset;
3463 int32val = (guint32*)p;
3464 *int32val = GUINT32_TO_LE (0); /* reserved */
3467 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3468 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3469 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3470 *p++ = 2; /* version */
3473 *p++ = 1; /* version */
3477 if (meta->idx_string_wide)
3479 if (meta->idx_guid_wide)
3481 if (meta->idx_blob_wide)
3484 *p++ = 1; /* reserved */
3485 int64val = (guint64*)p;
3486 *int64val++ = GUINT64_TO_LE (valid_mask);
3487 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3489 int32val = (guint32*)p;
3490 for (i = 0; i < MONO_TABLE_NUM; i++){
3491 if (meta->tables [i].rows == 0)
3493 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3495 p = (unsigned char*)int32val;
3497 /* sort the tables that still need sorting */
3498 table = &assembly->tables [MONO_TABLE_CONSTANT];
3500 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3501 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3503 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3504 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3506 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3507 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3509 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3510 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3512 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3513 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3514 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3516 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3518 /* compress the tables */
3519 for (i = 0; i < MONO_TABLE_NUM; i++){
3522 guint32 bitfield = meta->tables [i].size_bitfield;
3523 if (!meta->tables [i].rows)
3525 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3526 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3527 meta->tables [i].base = p;
3528 for (row = 1; row <= meta->tables [i].rows; ++row) {
3529 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3530 for (col = 0; col < assembly->tables [i].columns; ++col) {
3531 switch (mono_metadata_table_size (bitfield, col)) {
3533 *p++ = values [col];
3536 *p++ = values [col] & 0xff;
3537 *p++ = (values [col] >> 8) & 0xff;
3540 *p++ = values [col] & 0xff;
3541 *p++ = (values [col] >> 8) & 0xff;
3542 *p++ = (values [col] >> 16) & 0xff;
3543 *p++ = (values [col] >> 24) & 0xff;
3546 g_assert_not_reached ();
3550 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3553 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3554 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3555 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3556 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3557 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3559 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3563 * Some tables in metadata need to be sorted according to some criteria, but
3564 * when methods and fields are first created with reflection, they may be assigned a token
3565 * that doesn't correspond to the final token they will get assigned after the sorting.
3566 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3567 * with the reflection objects that represent them. Once all the tables are set up, the
3568 * reflection objects will contains the correct table index. fixup_method() will fixup the
3569 * tokens for the method with ILGenerator @ilgen.
3572 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3573 guint32 code_idx = GPOINTER_TO_UINT (value);
3574 MonoReflectionILTokenInfo *iltoken;
3575 MonoReflectionFieldBuilder *field;
3576 MonoReflectionCtorBuilder *ctor;
3577 MonoReflectionMethodBuilder *method;
3578 MonoReflectionTypeBuilder *tb;
3579 MonoReflectionArrayMethod *am;
3581 unsigned char *target;
3583 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3584 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3585 target = assembly->code.data + code_idx + iltoken->code_pos;
3586 switch (target [3]) {
3587 case MONO_TABLE_FIELD:
3588 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3589 field = (MonoReflectionFieldBuilder *)iltoken->member;
3590 idx = field->table_idx;
3591 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3592 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3593 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3595 g_assert_not_reached ();
3598 case MONO_TABLE_METHOD:
3599 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3600 method = (MonoReflectionMethodBuilder *)iltoken->member;
3601 idx = method->table_idx;
3602 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3603 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3604 idx = ctor->table_idx;
3605 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3606 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3607 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3608 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3610 g_assert_not_reached ();
3613 case MONO_TABLE_TYPEDEF:
3614 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3615 g_assert_not_reached ();
3616 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3617 idx = tb->table_idx;
3619 case MONO_TABLE_MEMBERREF:
3620 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3621 am = (MonoReflectionArrayMethod*)iltoken->member;
3622 idx = am->table_idx;
3623 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3624 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3625 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3626 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3627 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3628 g_assert (m->klass->generic_class || m->klass->generic_container);
3630 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3632 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3633 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3634 g_assert (f->generic_info);
3636 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3639 g_assert_not_reached ();
3642 case MONO_TABLE_METHODSPEC:
3643 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3644 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3645 g_assert (mono_method_signature (m)->generic_param_count);
3648 g_assert_not_reached ();
3652 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3654 target [0] = idx & 0xff;
3655 target [1] = (idx >> 8) & 0xff;
3656 target [2] = (idx >> 16) & 0xff;
3663 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3664 * value is not known when the table is emitted.
3667 fixup_cattrs (MonoDynamicImage *assembly)
3669 MonoDynamicTable *table;
3671 guint32 type, i, idx, token;
3674 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3676 for (i = 0; i < table->rows; ++i) {
3677 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3679 type = values [MONO_CUSTOM_ATTR_TYPE];
3680 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3681 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3682 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3683 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3686 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3687 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3688 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3689 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3696 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3698 MonoDynamicTable *table;
3701 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3703 alloc_table (table, table->rows);
3704 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3705 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3706 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3707 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3708 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3713 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3715 MonoDynamicTable *table;
3719 char *b = blob_size;
3721 guint32 idx, offset;
3723 if (rsrc->filename) {
3724 name = mono_string_to_utf8 (rsrc->filename);
3725 sname = g_path_get_basename (name);
3727 table = &assembly->tables [MONO_TABLE_FILE];
3729 alloc_table (table, table->rows);
3730 values = table->values + table->next_idx * MONO_FILE_SIZE;
3731 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3732 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3735 mono_sha1_get_digest_from_file (name, hash);
3736 mono_metadata_encode_value (20, b, &b);
3737 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3738 mono_image_add_stream_data (&assembly->blob, hash, 20);
3740 idx = table->next_idx++;
3742 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3748 data = mono_array_addr (rsrc->data, char, 0);
3749 len = mono_array_length (rsrc->data);
3755 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3756 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3757 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3758 mono_image_add_stream_data (&assembly->resources, data, len);
3762 * The entry should be emitted into the MANIFESTRESOURCE table of
3763 * the main module, but that needs to reference the FILE table
3764 * which isn't emitted yet.
3771 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3775 set_version_from_string (MonoString *version, guint32 *values)
3777 gchar *ver, *p, *str;
3780 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3781 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3782 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3783 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3786 ver = str = mono_string_to_utf8 (version);
3787 for (i = 0; i < 4; ++i) {
3788 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3794 /* handle Revision and Build */
3804 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3808 char *b = blob_size;
3813 len = mono_array_length (pkey);
3814 mono_metadata_encode_value (len, b, &b);
3815 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3816 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3818 /* Special case: check for ECMA key (16 bytes) */
3819 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, guint8, 0), len)) {
3820 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3821 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3822 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3823 /* minimum key size (in 2.0) is 384 bits */
3824 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3826 /* FIXME - verifier */
3827 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3828 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3830 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3836 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3838 MonoDynamicTable *table;
3839 MonoDynamicImage *assembly;
3840 MonoReflectionAssemblyBuilder *assemblyb;
3844 guint32 module_index;
3846 assemblyb = moduleb->assemblyb;
3847 assembly = moduleb->dynamic_image;
3848 domain = mono_object_domain (assemblyb);
3850 /* Emit ASSEMBLY table */
3851 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3852 alloc_table (table, 1);
3853 values = table->values + MONO_ASSEMBLY_SIZE;
3854 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3855 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3856 if (assemblyb->culture) {
3857 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3859 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3861 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3862 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3863 set_version_from_string (assemblyb->version, values);
3865 /* Emit FILE + EXPORTED_TYPE table */
3867 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3869 MonoReflectionModuleBuilder *file_module =
3870 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3871 if (file_module != moduleb) {
3872 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3874 if (file_module->types) {
3875 for (j = 0; j < file_module->num_types; ++j) {
3876 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3877 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3882 if (assemblyb->loaded_modules) {
3883 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3884 MonoReflectionModule *file_module =
3885 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3886 mono_image_fill_file_table (domain, file_module, assembly);
3888 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3891 if (assemblyb->type_forwarders)
3892 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3894 /* Emit MANIFESTRESOURCE table */
3896 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3898 MonoReflectionModuleBuilder *file_module =
3899 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3900 /* The table for the main module is emitted later */
3901 if (file_module != moduleb) {
3903 if (file_module->resources) {
3904 int len = mono_array_length (file_module->resources);
3905 for (j = 0; j < len; ++j) {
3906 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3907 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3915 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3916 * for the modulebuilder @moduleb.
3917 * At the end of the process, method and field tokens are fixed up and the
3918 * on-disk compressed metadata representation is created.
3921 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3923 MonoDynamicTable *table;
3924 MonoDynamicImage *assembly;
3925 MonoReflectionAssemblyBuilder *assemblyb;
3931 assemblyb = moduleb->assemblyb;
3932 assembly = moduleb->dynamic_image;
3933 domain = mono_object_domain (assemblyb);
3935 if (assembly->text_rva)
3938 assembly->text_rva = START_TEXT_RVA;
3940 if (moduleb->is_main) {
3941 mono_image_emit_manifest (moduleb);
3944 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3945 table->rows = 1; /* .<Module> */
3947 alloc_table (table, table->rows);
3949 * Set the first entry.
3951 values = table->values + table->columns;
3952 values [MONO_TYPEDEF_FLAGS] = 0;
3953 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3954 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3955 values [MONO_TYPEDEF_EXTENDS] = 0;
3956 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3957 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3960 * handle global methods
3961 * FIXME: test what to do when global methods are defined in multiple modules.
3963 if (moduleb->global_methods) {
3964 table = &assembly->tables [MONO_TABLE_METHOD];
3965 table->rows += mono_array_length (moduleb->global_methods);
3966 alloc_table (table, table->rows);
3967 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3968 mono_image_get_method_info (
3969 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3971 if (moduleb->global_fields) {
3972 table = &assembly->tables [MONO_TABLE_FIELD];
3973 table->rows += mono_array_length (moduleb->global_fields);
3974 alloc_table (table, table->rows);
3975 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3976 mono_image_get_field_info (
3977 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3980 table = &assembly->tables [MONO_TABLE_MODULE];
3981 alloc_table (table, 1);
3982 mono_image_fill_module_table (domain, moduleb, assembly);
3984 /* Collect all types into a list sorted by their table_idx */
3985 types = g_ptr_array_new ();
3988 for (i = 0; i < moduleb->num_types; ++i) {
3989 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3990 collect_types (types, type);
3993 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3994 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3995 table->rows += types->len;
3996 alloc_table (table, table->rows);
3999 * Emit type names + namespaces at one place inside the string heap,
4000 * so load_class_names () needs to touch fewer pages.
4002 for (i = 0; i < types->len; ++i) {
4003 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4004 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4006 for (i = 0; i < types->len; ++i) {
4007 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4008 string_heap_insert_mstring (&assembly->sheap, tb->name);
4011 for (i = 0; i < types->len; ++i) {
4012 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4013 mono_image_get_type_info (domain, type, assembly);
4017 * table->rows is already set above and in mono_image_fill_module_table.
4019 /* add all the custom attributes at the end, once all the indexes are stable */
4020 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4022 /* CAS assembly permissions */
4023 if (assemblyb->permissions_minimum)
4024 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4025 if (assemblyb->permissions_optional)
4026 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4027 if (assemblyb->permissions_refused)
4028 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4030 module_add_cattrs (assembly, moduleb);
4033 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4035 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4036 * the final tokens and don't need another fixup pass. */
4038 if (moduleb->global_methods) {
4039 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4040 MonoReflectionMethodBuilder *mb = mono_array_get (
4041 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4042 mono_image_add_methodimpl (assembly, mb);
4046 for (i = 0; i < types->len; ++i) {
4047 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4048 if (type->methods) {
4049 for (j = 0; j < type->num_methods; ++j) {
4050 MonoReflectionMethodBuilder *mb = mono_array_get (
4051 type->methods, MonoReflectionMethodBuilder*, j);
4053 mono_image_add_methodimpl (assembly, mb);
4058 g_ptr_array_free (types, TRUE);
4060 fixup_cattrs (assembly);
4064 * mono_image_insert_string:
4065 * @module: module builder object
4068 * Insert @str into the user string stream of @module.
4071 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4073 MonoDynamicImage *assembly;
4078 MONO_ARCH_SAVE_REGS;
4080 if (!module->dynamic_image)
4081 mono_image_module_basic_init (module);
4083 assembly = module->dynamic_image;
4085 if (assembly->save) {
4086 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4087 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4088 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4090 char *swapped = g_malloc (2 * mono_string_length (str));
4091 const char *p = (const char*)mono_string_chars (str);
4093 swap_with_size (swapped, p, 2, mono_string_length (str));
4094 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4098 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4100 mono_image_add_stream_data (&assembly->us, "", 1);
4102 idx = assembly->us.index ++;
4105 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4107 return MONO_TOKEN_STRING | idx;
4111 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4116 klass = obj->vtable->klass;
4117 if (strcmp (klass->name, "MonoMethod") == 0) {
4118 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4119 MonoMethodSignature *sig, *old;
4120 guint32 sig_token, parent;
4123 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4125 nargs = mono_array_length (opt_param_types);
4126 old = mono_method_signature (method);
4127 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4129 sig->hasthis = old->hasthis;
4130 sig->explicit_this = old->explicit_this;
4131 sig->call_convention = old->call_convention;
4132 sig->generic_param_count = old->generic_param_count;
4133 sig->param_count = old->param_count + nargs;
4134 sig->sentinelpos = old->param_count;
4135 sig->ret = old->ret;
4137 for (i = 0; i < old->param_count; i++)
4138 sig->params [i] = old->params [i];
4140 for (i = 0; i < nargs; i++) {
4141 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4142 sig->params [old->param_count + i] = rt->type;
4145 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4146 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4147 parent >>= MONO_TYPEDEFORREF_BITS;
4149 parent <<= MONO_MEMBERREF_PARENT_BITS;
4150 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4152 sig_token = method_encode_signature (assembly, sig);
4153 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4154 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4155 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4156 ReflectionMethodBuilder rmb;
4157 guint32 parent, sig;
4159 reflection_methodbuilder_from_method_builder (&rmb, mb);
4160 rmb.opt_types = opt_param_types;
4162 sig = method_builder_encode_signature (assembly, &rmb);
4164 parent = mono_image_create_token (assembly, obj, TRUE);
4165 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4167 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4168 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4170 token = mono_image_get_varargs_method_token (
4171 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4173 g_error ("requested method token for %s\n", klass->name);
4180 * mono_image_create_token:
4181 * @assembly: a dynamic assembly
4184 * Get a token to insert in the IL code stream for the given MemberInfo.
4185 * @obj can be one of:
4186 * ConstructorBuilder
4196 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4201 klass = obj->vtable->klass;
4202 if (strcmp (klass->name, "MethodBuilder") == 0) {
4203 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4205 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4206 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4208 token = mono_image_get_methodbuilder_token (assembly, mb);
4209 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4210 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4211 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4213 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4214 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4216 token = mono_image_get_ctorbuilder_token (assembly, mb);
4217 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4218 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4219 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4220 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4221 if (tb->generic_params) {
4222 token = mono_image_get_generic_field_token (assembly, fb);
4224 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4226 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4227 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4228 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4229 } else if (strcmp (klass->name, "MonoType") == 0 ||
4230 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4231 MonoReflectionType *tb = (MonoReflectionType *)obj;
4232 token = mono_metadata_token_from_dor (
4233 mono_image_typedef_or_ref (assembly, tb->type));
4234 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4235 MonoReflectionType *tb = (MonoReflectionType *)obj;
4236 token = mono_metadata_token_from_dor (
4237 mono_image_typedef_or_ref (assembly, tb->type));
4238 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4239 strcmp (klass->name, "MonoMethod") == 0 ||
4240 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4241 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4242 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4243 if (m->method->is_inflated) {
4244 if (create_methodspec)
4245 token = mono_image_get_methodspec_token (assembly, m->method);
4247 token = mono_image_get_inflated_method_token (assembly, m->method);
4248 } else if ((m->method->klass->image == &assembly->image) &&
4249 !m->method->klass->generic_class) {
4250 static guint32 method_table_idx = 0xffffff;
4251 if (m->method->klass->wastypebuilder) {
4252 /* we use the same token as the one that was assigned
4253 * to the Methodbuilder.
4254 * FIXME: do the equivalent for Fields.
4256 token = m->method->token;
4259 * Each token should have a unique index, but the indexes are
4260 * assigned by managed code, so we don't know about them. An
4261 * easy solution is to count backwards...
4263 method_table_idx --;
4264 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4267 token = mono_image_get_methodref_token (assembly, m->method);
4269 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4270 } else if (strcmp (klass->name, "MonoField") == 0) {
4271 MonoReflectionField *f = (MonoReflectionField *)obj;
4272 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4273 static guint32 field_table_idx = 0xffffff;
4275 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4277 token = mono_image_get_fieldref_token (assembly, f);
4279 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4280 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4281 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4282 token = mono_image_get_array_token (assembly, m);
4283 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4284 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4285 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4286 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4287 MonoReflectionType *tb = (MonoReflectionType *)obj;
4288 token = mono_metadata_token_from_dor (
4289 mono_image_typedef_or_ref (assembly, tb->type));
4291 g_error ("requested token for %s\n", klass->name);
4294 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4300 guint32 import_lookup_table;
4304 guint32 import_address_table_rva;
4312 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4314 static MonoDynamicImage*
4315 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4317 static const guchar entrycode [16] = {0xff, 0x25, 0};
4318 MonoDynamicImage *image;
4321 const char *version = mono_get_runtime_info ()->runtime_version;
4324 image = GC_MALLOC (sizeof (MonoDynamicImage));
4326 image = g_new0 (MonoDynamicImage, 1);
4329 /*g_print ("created image %p\n", image);*/
4330 /* keep in sync with image.c */
4331 image->image.name = assembly_name;
4332 image->image.assembly_name = image->image.name; /* they may be different */
4333 image->image.module_name = module_name;
4334 image->image.version = g_strdup (version);
4335 image->image.md_version_major = 1;
4336 image->image.md_version_minor = 1;
4337 image->image.dynamic = TRUE;
4339 image->image.references = g_new0 (MonoAssembly*, 1);
4340 image->image.references [0] = NULL;
4342 mono_image_init (&image->image);
4344 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4345 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4346 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4347 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4348 image->handleref = g_hash_table_new (NULL, NULL);
4349 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4350 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4351 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4352 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4353 image->gen_params = g_ptr_array_new ();
4355 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4356 string_heap_init (&image->sheap);
4357 mono_image_add_stream_data (&image->us, "", 1);
4358 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4359 /* import tables... */
4360 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4361 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4362 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4363 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4364 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4365 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4366 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4367 stream_data_align (&image->code);
4369 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4371 for (i=0; i < MONO_TABLE_NUM; ++i) {
4372 image->tables [i].next_idx = 1;
4373 image->tables [i].columns = table_sizes [i];
4376 image->image.assembly = (MonoAssembly*)assembly;
4377 image->run = assembly->run;
4378 image->save = assembly->save;
4379 image->pe_kind = 0x1; /* ILOnly */
4380 image->machine = 0x14c; /* I386 */
4386 * mono_image_basic_init:
4387 * @assembly: an assembly builder object
4389 * Create the MonoImage that represents the assembly builder and setup some
4390 * of the helper hash table and the basic metadata streams.
4393 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4395 MonoDynamicAssembly *assembly;
4396 MonoDynamicImage *image;
4397 MonoDomain *domain = mono_object_domain (assemblyb);
4399 MONO_ARCH_SAVE_REGS;
4401 if (assemblyb->dynamic_assembly)
4405 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4407 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4410 assembly->assembly.ref_count = 1;
4411 assembly->assembly.dynamic = TRUE;
4412 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4413 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4414 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4415 if (assemblyb->culture)
4416 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4418 assembly->assembly.aname.culture = g_strdup ("");
4420 if (assemblyb->version) {
4421 char *vstr = mono_string_to_utf8 (assemblyb->version);
4422 char **version = g_strsplit (vstr, ".", 4);
4423 char **parts = version;
4424 assembly->assembly.aname.major = atoi (*parts++);
4425 assembly->assembly.aname.minor = atoi (*parts++);
4426 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4427 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4429 g_strfreev (version);
4432 assembly->assembly.aname.major = 0;
4433 assembly->assembly.aname.minor = 0;
4434 assembly->assembly.aname.build = 0;
4435 assembly->assembly.aname.revision = 0;
4438 assembly->run = assemblyb->access != 2;
4439 assembly->save = assemblyb->access != 1;
4441 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4442 image->initial_image = TRUE;
4443 assembly->assembly.aname.name = image->image.name;
4444 assembly->assembly.image = &image->image;
4446 mono_domain_assemblies_lock (domain);
4447 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4448 mono_domain_assemblies_unlock (domain);
4450 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4451 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4455 calc_section_size (MonoDynamicImage *assembly)
4459 /* alignment constraints */
4460 assembly->code.index += 3;
4461 assembly->code.index &= ~3;
4462 assembly->meta_size += 3;
4463 assembly->meta_size &= ~3;
4464 assembly->resources.index += 3;
4465 assembly->resources.index &= ~3;
4467 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4468 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4471 if (assembly->win32_res) {
4472 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4474 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4475 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4479 assembly->sections [MONO_SECTION_RELOC].size = 12;
4480 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4490 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4494 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4496 ResTreeNode *t1 = (ResTreeNode*)a;
4497 ResTreeNode *t2 = (ResTreeNode*)b;
4499 return t1->id - t2->id;
4503 * resource_tree_create:
4505 * Organize the resources into a resource tree.
4507 static ResTreeNode *
4508 resource_tree_create (MonoArray *win32_resources)
4510 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4514 tree = g_new0 (ResTreeNode, 1);
4516 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4517 MonoReflectionWin32Resource *win32_res =
4518 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4522 /* FIXME: BUG: this stores managed references in unmanaged memory */
4523 lang_node = g_new0 (ResTreeNode, 1);
4524 lang_node->id = win32_res->lang_id;
4525 lang_node->win32_res = win32_res;
4527 /* Create type node if neccesary */
4529 for (l = tree->children; l; l = l->next)
4530 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4531 type_node = (ResTreeNode*)l->data;
4536 type_node = g_new0 (ResTreeNode, 1);
4537 type_node->id = win32_res->res_type;
4540 * The resource types have to be sorted otherwise
4541 * Windows Explorer can't display the version information.
4543 tree->children = g_slist_insert_sorted (tree->children,
4544 type_node, resource_tree_compare_by_id);
4547 /* Create res node if neccesary */
4549 for (l = type_node->children; l; l = l->next)
4550 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4551 res_node = (ResTreeNode*)l->data;
4556 res_node = g_new0 (ResTreeNode, 1);
4557 res_node->id = win32_res->res_id;
4558 type_node->children = g_slist_append (type_node->children, res_node);
4561 res_node->children = g_slist_append (res_node->children, lang_node);
4568 * resource_tree_encode:
4570 * Encode the resource tree into the format used in the PE file.
4573 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4576 MonoPEResourceDir dir;
4577 MonoPEResourceDirEntry dir_entry;
4578 MonoPEResourceDataEntry data_entry;
4582 * For the format of the resource directory, see the article
4583 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4587 memset (&dir, 0, sizeof (dir));
4588 memset (&dir_entry, 0, sizeof (dir_entry));
4589 memset (&data_entry, 0, sizeof (data_entry));
4591 g_assert (sizeof (dir) == 16);
4592 g_assert (sizeof (dir_entry) == 8);
4593 g_assert (sizeof (data_entry) == 16);
4595 node->offset = p - begin;
4597 /* IMAGE_RESOURCE_DIRECTORY */
4598 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4600 memcpy (p, &dir, sizeof (dir));
4603 /* Reserve space for entries */
4605 p += sizeof (dir_entry) * dir.res_id_entries;
4607 /* Write children */
4608 for (l = node->children; l; l = l->next) {
4609 ResTreeNode *child = (ResTreeNode*)l->data;
4611 if (child->win32_res) {
4613 child->offset = p - begin;
4615 /* IMAGE_RESOURCE_DATA_ENTRY */
4616 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4617 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4619 memcpy (p, &data_entry, sizeof (data_entry));
4620 p += sizeof (data_entry);
4622 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4623 p += data_entry.rde_size;
4625 resource_tree_encode (child, begin, p, &p);
4629 /* IMAGE_RESOURCE_ENTRY */
4630 for (l = node->children; l; l = l->next) {
4631 ResTreeNode *child = (ResTreeNode*)l->data;
4632 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4634 dir_entry.is_dir = child->win32_res ? 0 : 1;
4635 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4637 memcpy (entries, &dir_entry, sizeof (dir_entry));
4638 entries += sizeof (dir_entry);
4645 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4650 MonoReflectionWin32Resource *win32_res;
4653 if (!assemblyb->win32_resources)
4657 * Resources are stored in a three level tree inside the PE file.
4658 * - level one contains a node for each type of resource
4659 * - level two contains a node for each resource
4660 * - level three contains a node for each instance of a resource for a
4661 * specific language.
4664 tree = resource_tree_create (assemblyb->win32_resources);
4666 /* Estimate the size of the encoded tree */
4668 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4669 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4670 size += mono_array_length (win32_res->res_data);
4672 /* Directory structure */
4673 size += mono_array_length (assemblyb->win32_resources) * 256;
4674 p = buf = g_malloc (size);
4676 resource_tree_encode (tree, p, p, &p);
4678 g_assert (p - buf < size);
4680 assembly->win32_res = g_malloc (p - buf);
4681 assembly->win32_res_size = p - buf;
4682 memcpy (assembly->win32_res, buf, p - buf);
4688 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4690 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4693 p += sizeof (MonoPEResourceDir);
4694 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4695 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4696 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4697 if (dir_entry->is_dir) {
4698 fixup_resource_directory (res_section, child, rva);
4700 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4701 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4704 p += sizeof (MonoPEResourceDirEntry);
4709 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4712 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4713 g_error ("WriteFile returned %d\n", GetLastError ());
4717 * mono_image_create_pefile:
4718 * @mb: a module builder object
4720 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4721 * assembly->pefile where it can be easily retrieved later in chunks.
4724 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4725 MonoMSDOSHeader *msdos;
4726 MonoDotNetHeader *header;
4727 MonoSectionTable *section;
4728 MonoCLIHeader *cli_header;
4729 guint32 size, image_size, virtual_base, text_offset;
4730 guint32 header_start, section_start, file_offset, virtual_offset;
4731 MonoDynamicImage *assembly;
4732 MonoReflectionAssemblyBuilder *assemblyb;
4733 MonoDynamicStream pefile_stream = {0};
4734 MonoDynamicStream *pefile = &pefile_stream;
4736 guint32 *rva, value;
4738 static const unsigned char msheader[] = {
4739 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4740 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4741 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4743 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4744 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4745 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4746 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4749 assemblyb = mb->assemblyb;
4751 mono_image_basic_init (assemblyb);
4752 assembly = mb->dynamic_image;
4754 assembly->pe_kind = assemblyb->pe_kind;
4755 assembly->machine = assemblyb->machine;
4756 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4757 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4759 mono_image_build_metadata (mb);
4761 if (mb->is_main && assemblyb->resources) {
4762 int len = mono_array_length (assemblyb->resources);
4763 for (i = 0; i < len; ++i)
4764 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4767 if (mb->resources) {
4768 int len = mono_array_length (mb->resources);
4769 for (i = 0; i < len; ++i)
4770 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4773 build_compressed_metadata (assembly);
4776 assembly_add_win32_resources (assembly, assemblyb);
4778 nsections = calc_section_size (assembly);
4780 /* The DOS header and stub */
4781 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4782 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4784 /* the dotnet header */
4785 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4787 /* the section tables */
4788 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4790 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4791 virtual_offset = VIRT_ALIGN;
4794 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4795 if (!assembly->sections [i].size)
4798 file_offset += FILE_ALIGN - 1;
4799 file_offset &= ~(FILE_ALIGN - 1);
4800 virtual_offset += VIRT_ALIGN - 1;
4801 virtual_offset &= ~(VIRT_ALIGN - 1);
4803 assembly->sections [i].offset = file_offset;
4804 assembly->sections [i].rva = virtual_offset;
4806 file_offset += assembly->sections [i].size;
4807 virtual_offset += assembly->sections [i].size;
4808 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4811 file_offset += FILE_ALIGN - 1;
4812 file_offset &= ~(FILE_ALIGN - 1);
4814 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4816 /* back-patch info */
4817 msdos = (MonoMSDOSHeader*)pefile->data;
4818 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4820 header = (MonoDotNetHeader*)(pefile->data + header_start);
4821 header->pesig [0] = 'P';
4822 header->pesig [1] = 'E';
4824 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4825 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4826 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4827 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4828 if (assemblyb->pekind == 1) {
4830 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4833 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4836 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4838 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4839 header->pe.pe_major = 6;
4840 header->pe.pe_minor = 0;
4841 size = assembly->sections [MONO_SECTION_TEXT].size;
4842 size += FILE_ALIGN - 1;
4843 size &= ~(FILE_ALIGN - 1);
4844 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4845 size = assembly->sections [MONO_SECTION_RSRC].size;
4846 size += FILE_ALIGN - 1;
4847 size &= ~(FILE_ALIGN - 1);
4848 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4849 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4850 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4851 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4852 /* pe_rva_entry_point always at the beginning of the text section */
4853 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4855 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4856 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4857 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4858 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4859 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4860 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4861 size = section_start;
4862 size += FILE_ALIGN - 1;
4863 size &= ~(FILE_ALIGN - 1);
4864 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4866 size += VIRT_ALIGN - 1;
4867 size &= ~(VIRT_ALIGN - 1);
4868 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4871 // Translate the PEFileKind value to the value expected by the Windows loader
4877 // PEFileKinds.Dll == 1
4878 // PEFileKinds.ConsoleApplication == 2
4879 // PEFileKinds.WindowApplication == 3
4882 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4883 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4885 if (assemblyb->pekind == 3)
4890 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4892 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4893 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4894 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4895 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4896 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4897 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4899 /* fill data directory entries */
4901 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4902 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4904 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4905 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4907 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4908 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4909 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4910 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4911 /* patch entrypoint name */
4912 if (assemblyb->pekind == 1)
4913 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4915 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4916 /* patch imported function RVA name */
4917 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4918 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4920 /* the import table */
4921 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4922 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4923 /* patch imported dll RVA name and other entries in the dir */
4924 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4925 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4926 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4927 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4928 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4929 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4931 p = (assembly->code.data + assembly->ilt_offset);
4932 value = (assembly->text_rva + assembly->imp_names_offset);
4933 *p++ = (value) & 0xff;
4934 *p++ = (value >> 8) & (0xff);
4935 *p++ = (value >> 16) & (0xff);
4936 *p++ = (value >> 24) & (0xff);
4938 /* the CLI header info */
4939 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4940 cli_header->ch_size = GUINT32_FROM_LE (72);
4941 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4942 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4943 if (assemblyb->entry_point) {
4944 guint32 table_idx = 0;
4945 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4946 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4947 table_idx = methodb->table_idx;
4949 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4951 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4953 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4955 /* The embedded managed resources */
4956 text_offset = assembly->text_rva + assembly->code.index;
4957 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4958 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4959 text_offset += assembly->resources.index;
4960 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4961 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4962 text_offset += assembly->meta_size;
4963 if (assembly->strong_name_size) {
4964 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4965 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4966 text_offset += assembly->strong_name_size;
4969 /* write the section tables and section content */
4970 section = (MonoSectionTable*)(pefile->data + section_start);
4971 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4972 static const char section_names [][7] = {
4973 ".text", ".rsrc", ".reloc"
4975 if (!assembly->sections [i].size)
4977 strcpy (section->st_name, section_names [i]);
4978 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4979 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4980 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4981 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4982 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4983 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4984 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4988 checked_write_file (file, pefile->data, pefile->index);
4990 mono_dynamic_stream_reset (pefile);
4992 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4993 if (!assembly->sections [i].size)
4996 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4997 g_error ("SetFilePointer returned %d\n", GetLastError ());
5000 case MONO_SECTION_TEXT:
5001 /* patch entry point */
5002 p = (assembly->code.data + 2);
5003 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5004 *p++ = (value) & 0xff;
5005 *p++ = (value >> 8) & 0xff;
5006 *p++ = (value >> 16) & 0xff;
5007 *p++ = (value >> 24) & 0xff;
5009 checked_write_file (file, assembly->code.data, assembly->code.index);
5010 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5011 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5012 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5015 g_free (assembly->image.raw_metadata);
5017 case MONO_SECTION_RELOC: {
5021 guint16 type_and_offset;
5025 g_assert (sizeof (reloc) == 12);
5027 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5028 reloc.block_size = GUINT32_FROM_LE (12);
5031 * the entrypoint is always at the start of the text section
5032 * 3 is IMAGE_REL_BASED_HIGHLOW
5033 * 2 is patch_size_rva - text_rva
5035 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5038 checked_write_file (file, &reloc, sizeof (reloc));
5042 case MONO_SECTION_RSRC:
5043 if (assembly->win32_res) {
5045 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5046 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5047 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5051 g_assert_not_reached ();
5055 /* check that the file is properly padded */
5056 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5057 g_error ("SetFilePointer returned %d\n", GetLastError ());
5058 if (! SetEndOfFile (file))
5059 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5061 mono_dynamic_stream_reset (&assembly->code);
5062 mono_dynamic_stream_reset (&assembly->us);
5063 mono_dynamic_stream_reset (&assembly->blob);
5064 mono_dynamic_stream_reset (&assembly->guid);
5065 mono_dynamic_stream_reset (&assembly->sheap);
5067 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5068 g_hash_table_destroy (assembly->blob_cache);
5069 assembly->blob_cache = NULL;
5072 MonoReflectionModule *
5073 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5077 MonoImageOpenStatus status;
5078 MonoDynamicAssembly *assembly;
5079 guint32 module_count;
5080 MonoImage **new_modules;
5082 name = mono_string_to_utf8 (fileName);
5084 image = mono_image_open (name, &status);
5087 if (status == MONO_IMAGE_ERROR_ERRNO)
5088 exc = mono_get_exception_file_not_found (fileName);
5090 exc = mono_get_exception_bad_image_format (name);
5092 mono_raise_exception (exc);
5097 assembly = ab->dynamic_assembly;
5098 image->assembly = (MonoAssembly*)assembly;
5100 module_count = image->assembly->image->module_count;
5101 new_modules = g_new0 (MonoImage *, module_count + 1);
5103 if (image->assembly->image->modules)
5104 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5105 new_modules [module_count] = image;
5106 mono_image_addref (image);
5108 g_free (image->assembly->image->modules);
5109 image->assembly->image->modules = new_modules;
5110 image->assembly->image->module_count ++;
5112 mono_assembly_load_references (image, &status);
5114 mono_image_close (image);
5115 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5118 return mono_module_get_object (mono_domain_get (), image);
5122 * We need to return always the same object for MethodInfo, FieldInfo etc..
5123 * but we need to consider the reflected type.
5124 * type uses a different hash, since it uses custom hash/equal functions.
5129 MonoClass *refclass;
5133 reflected_equal (gconstpointer a, gconstpointer b) {
5134 const ReflectedEntry *ea = a;
5135 const ReflectedEntry *eb = b;
5137 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5141 reflected_hash (gconstpointer a) {
5142 const ReflectedEntry *ea = a;
5143 return mono_aligned_addr_hash (ea->item);
5146 #define CHECK_OBJECT(t,p,k) \
5152 mono_domain_lock (domain); \
5153 if (!domain->refobject_hash) \
5154 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5155 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5156 mono_domain_unlock (domain); \
5159 mono_domain_unlock (domain); \
5163 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5165 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5167 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5170 #define CACHE_OBJECT(t,p,o,k) \
5173 ReflectedEntry pe; \
5175 pe.refclass = (k); \
5176 mono_domain_lock (domain); \
5177 if (!domain->refobject_hash) \
5178 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5179 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5181 ReflectedEntry *e = ALLOC_REFENTRY; \
5183 e->refclass = (k); \
5184 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5187 mono_domain_unlock (domain); \
5192 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5194 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5198 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5200 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5204 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5206 MonoDynamicImage *image = moduleb->dynamic_image;
5207 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5210 MonoImage **new_modules;
5213 * FIXME: we already created an image in mono_image_basic_init (), but
5214 * we don't know which module it belongs to, since that is only
5215 * determined at assembly save time.
5217 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5218 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5220 moduleb->module.image = &image->image;
5221 moduleb->dynamic_image = image;
5222 register_module (mono_object_domain (moduleb), moduleb, image);
5224 /* register the module with the assembly */
5225 ass = ab->dynamic_assembly->assembly.image;
5226 module_count = ass->module_count;
5227 new_modules = g_new0 (MonoImage *, module_count + 1);
5230 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5231 new_modules [module_count] = &image->image;
5232 mono_image_addref (&image->image);
5234 g_free (ass->modules);
5235 ass->modules = new_modules;
5236 ass->module_count ++;
5241 * mono_assembly_get_object:
5242 * @domain: an app domain
5243 * @assembly: an assembly
5245 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5247 MonoReflectionAssembly*
5248 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5250 static MonoClass *System_Reflection_Assembly;
5251 MonoReflectionAssembly *res;
5253 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5254 if (!System_Reflection_Assembly)
5255 System_Reflection_Assembly = mono_class_from_name (
5256 mono_defaults.corlib, "System.Reflection", "Assembly");
5257 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5258 res->assembly = assembly;
5260 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5265 MonoReflectionModule*
5266 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5268 static MonoClass *System_Reflection_Module;
5269 MonoReflectionModule *res;
5272 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5273 if (!System_Reflection_Module)
5274 System_Reflection_Module = mono_class_from_name (
5275 mono_defaults.corlib, "System.Reflection", "Module");
5276 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5279 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5281 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5282 basename = g_path_get_basename (image->name);
5283 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5284 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5288 if (image->assembly->image == image) {
5289 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5293 if (image->assembly->image->modules) {
5294 for (i = 0; i < image->assembly->image->module_count; i++) {
5295 if (image->assembly->image->modules [i] == image)
5296 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5298 g_assert (res->token);
5302 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5305 MonoReflectionModule*
5306 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5308 static MonoClass *System_Reflection_Module;
5309 MonoReflectionModule *res;
5310 MonoTableInfo *table;
5311 guint32 cols [MONO_FILE_SIZE];
5313 guint32 i, name_idx;
5316 if (!System_Reflection_Module)
5317 System_Reflection_Module = mono_class_from_name (
5318 mono_defaults.corlib, "System.Reflection", "Module");
5319 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5321 table = &image->tables [MONO_TABLE_FILE];
5322 g_assert (table_index < table->rows);
5323 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5326 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5327 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5329 /* Check whenever the row has a corresponding row in the moduleref table */
5330 table = &image->tables [MONO_TABLE_MODULEREF];
5331 for (i = 0; i < table->rows; ++i) {
5332 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5333 val = mono_metadata_string_heap (image, name_idx);
5334 if (strcmp (val, name) == 0)
5335 res->image = image->modules [i];
5338 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5339 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5340 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5341 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5342 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5348 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5350 if ((t1->type != t2->type) ||
5351 (t1->byref != t2->byref))
5355 case MONO_TYPE_VOID:
5356 case MONO_TYPE_BOOLEAN:
5357 case MONO_TYPE_CHAR:
5368 case MONO_TYPE_STRING:
5371 case MONO_TYPE_OBJECT:
5372 case MONO_TYPE_TYPEDBYREF:
5374 case MONO_TYPE_VALUETYPE:
5375 case MONO_TYPE_CLASS:
5376 case MONO_TYPE_SZARRAY:
5377 return t1->data.klass == t2->data.klass;
5379 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5380 case MONO_TYPE_ARRAY:
5381 if (t1->data.array->rank != t2->data.array->rank)
5383 return t1->data.array->eklass == t2->data.array->eklass;
5384 case MONO_TYPE_GENERICINST: {
5386 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5388 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5389 &t2->data.generic_class->container_class->byval_arg))
5391 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5392 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5398 case MONO_TYPE_MVAR:
5399 return t1->data.generic_param == t2->data.generic_param;
5401 g_error ("implement type compare for %0x!", t1->type);
5409 mymono_metadata_type_hash (MonoType *t1)
5415 hash |= t1->byref << 6; /* do not collide with t1->type values */
5417 case MONO_TYPE_VALUETYPE:
5418 case MONO_TYPE_CLASS:
5419 case MONO_TYPE_SZARRAY:
5420 /* check if the distribution is good enough */
5421 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5423 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5424 case MONO_TYPE_GENERICINST: {
5426 MonoGenericInst *inst = t1->data.generic_class->inst;
5427 hash += g_str_hash (t1->data.generic_class->container_class->name);
5429 for (i = 0; i < inst->type_argc; ++i) {
5430 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5439 static MonoReflectionGenericClass*
5440 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5442 static MonoClass *System_Reflection_MonoGenericClass;
5443 MonoReflectionGenericClass *res;
5444 MonoClass *klass, *gklass;
5446 if (!System_Reflection_MonoGenericClass) {
5447 System_Reflection_MonoGenericClass = mono_class_from_name (
5448 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5449 g_assert (System_Reflection_MonoGenericClass);
5452 klass = mono_class_from_mono_type (geninst);
5453 gklass = klass->generic_class->container_class;
5455 mono_class_init (klass);
5458 /* FIXME: allow unpinned later */
5459 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5461 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5464 res->type.type = geninst;
5465 if (gklass->wastypebuilder && gklass->reflection_info)
5466 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5468 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5474 verify_safe_for_managed_space (MonoType *type)
5476 switch (type->type) {
5478 case MONO_TYPE_ARRAY:
5479 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5481 return verify_safe_for_managed_space (type->data.type);
5482 case MONO_TYPE_SZARRAY:
5483 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5484 case MONO_TYPE_GENERICINST: {
5485 MonoGenericInst *inst = type->data.generic_class->inst;
5489 for (i = 0; i < inst->type_argc; ++i)
5490 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5496 case MONO_TYPE_MVAR:
5503 * mono_type_get_object:
5504 * @domain: an app domain
5507 * Return an System.MonoType object representing the type @type.
5510 mono_type_get_object (MonoDomain *domain, MonoType *type)
5512 MonoReflectionType *res;
5513 MonoClass *klass = mono_class_from_mono_type (type);
5515 mono_domain_lock (domain);
5516 if (!domain->type_hash)
5517 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5518 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5519 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5520 mono_domain_unlock (domain);
5523 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5524 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5525 mono_g_hash_table_insert (domain->type_hash, type, res);
5526 mono_domain_unlock (domain);
5530 if (!verify_safe_for_managed_space (type)) {
5531 mono_domain_unlock (domain);
5532 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5535 if (klass->reflection_info && !klass->wastypebuilder) {
5536 /* g_assert_not_reached (); */
5537 /* should this be considered an error condition? */
5539 mono_domain_unlock (domain);
5540 return klass->reflection_info;
5543 mono_class_init (klass);
5545 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5547 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5550 mono_g_hash_table_insert (domain->type_hash, type, res);
5551 mono_domain_unlock (domain);
5556 * mono_method_get_object:
5557 * @domain: an app domain
5559 * @refclass: the reflected type (can be NULL)
5561 * Return an System.Reflection.MonoMethod object representing the method @method.
5563 MonoReflectionMethod*
5564 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5567 * We use the same C representation for methods and constructors, but the type
5568 * name in C# is different.
5570 static MonoClass *System_Reflection_MonoMethod = NULL;
5571 static MonoClass *System_Reflection_MonoCMethod = NULL;
5572 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5573 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5576 MonoReflectionMethod *ret;
5578 if (method->is_inflated) {
5579 MonoReflectionGenericMethod *gret;
5581 method = mono_get_inflated_method (method);
5582 refclass = method->klass;
5583 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5584 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5585 if (!System_Reflection_MonoGenericCMethod)
5586 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5587 klass = System_Reflection_MonoGenericCMethod;
5589 if (!System_Reflection_MonoGenericMethod)
5590 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5591 klass = System_Reflection_MonoGenericMethod;
5593 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5594 gret->method.method = method;
5595 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5596 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5597 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5601 refclass = method->klass;
5603 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5604 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5605 if (!System_Reflection_MonoCMethod)
5606 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5607 klass = System_Reflection_MonoCMethod;
5610 if (!System_Reflection_MonoMethod)
5611 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5612 klass = System_Reflection_MonoMethod;
5614 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5615 ret->method = method;
5616 MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name));
5617 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5618 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5622 * mono_field_get_object:
5623 * @domain: an app domain
5627 * Return an System.Reflection.MonoField object representing the field @field
5630 MonoReflectionField*
5631 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5633 MonoReflectionField *res;
5636 CHECK_OBJECT (MonoReflectionField *, field, klass);
5637 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5638 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5641 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5642 if (field->generic_info)
5643 res->attrs = field->generic_info->generic_type->attrs;
5645 res->attrs = field->type->attrs;
5646 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5647 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5651 * mono_property_get_object:
5652 * @domain: an app domain
5654 * @property: a property
5656 * Return an System.Reflection.MonoProperty object representing the property @property
5659 MonoReflectionProperty*
5660 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5662 MonoReflectionProperty *res;
5665 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5666 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5667 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5669 res->property = property;
5670 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5674 * mono_event_get_object:
5675 * @domain: an app domain
5679 * Return an System.Reflection.MonoEvent object representing the event @event
5682 MonoReflectionEvent*
5683 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5685 MonoReflectionEvent *res;
5688 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5689 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5690 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5693 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5697 * mono_param_get_objects:
5698 * @domain: an app domain
5701 * Return an System.Reflection.ParameterInfo array object representing the parameters
5702 * in the method @method.
5705 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5707 static MonoClass *System_Reflection_ParameterInfo;
5708 MonoArray *res = NULL;
5709 MonoReflectionMethod *member = NULL;
5710 MonoReflectionParameter *param = NULL;
5711 char **names, **blobs = NULL;
5712 guint32 *types = NULL;
5713 MonoType *type = NULL;
5714 MonoObject *dbnull = mono_get_dbnull_object (domain);
5715 MonoMarshalSpec **mspecs;
5716 MonoMethodSignature *sig;
5719 if (!System_Reflection_ParameterInfo)
5720 System_Reflection_ParameterInfo = mono_class_from_name (
5721 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5723 if (!mono_method_signature (method)->param_count)
5724 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5726 /* Note: the cache is based on the address of the signature into the method
5727 * since we already cache MethodInfos with the method as keys.
5729 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5731 sig = mono_method_signature (method);
5732 member = mono_method_get_object (domain, method, NULL);
5733 names = g_new (char *, sig->param_count);
5734 mono_method_get_param_names (method, (const char **) names);
5736 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5737 mono_method_get_marshal_info (method, mspecs);
5739 res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5740 for (i = 0; i < sig->param_count; ++i) {
5741 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5742 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5743 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5744 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5745 param->PositionImpl = i;
5746 param->AttrsImpl = sig->params [i]->attrs;
5748 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5749 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5753 blobs = g_new0 (char *, sig->param_count);
5754 types = g_new0 (guint32, sig->param_count);
5755 get_default_param_value_blobs (method, blobs, types);
5758 /* Build MonoType for the type from the Constant Table */
5760 type = g_new0 (MonoType, 1);
5761 type->type = types [i];
5762 type->data.klass = NULL;
5763 if (types [i] == MONO_TYPE_CLASS)
5764 type->data.klass = mono_defaults.object_class;
5765 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5766 /* For enums, types [i] contains the base type */
5768 type->type = MONO_TYPE_VALUETYPE;
5769 type->data.klass = mono_class_from_mono_type (sig->params [i]);
5771 type->data.klass = mono_class_from_mono_type (type);
5773 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5775 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5776 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5777 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5782 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5784 mono_array_setref (res, i, param);
5791 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5793 mono_metadata_free_marshal_spec (mspecs [i]);
5796 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5800 * mono_method_body_get_object:
5801 * @domain: an app domain
5804 * Return an System.Reflection.MethodBody object representing the method @method.
5806 MonoReflectionMethodBody*
5807 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5809 static MonoClass *System_Reflection_MethodBody = NULL;
5810 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5811 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5812 MonoReflectionMethodBody *ret;
5813 MonoMethodNormal *mn;
5814 MonoMethodHeader *header;
5815 guint32 method_rva, local_var_sig_token;
5817 unsigned char format, flags;
5820 if (!System_Reflection_MethodBody)
5821 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5822 if (!System_Reflection_LocalVariableInfo)
5823 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5824 if (!System_Reflection_ExceptionHandlingClause)
5825 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5827 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5829 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5830 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5831 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5832 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5834 mn = (MonoMethodNormal *)method;
5835 header = mono_method_get_header (method);
5837 /* Obtain local vars signature token */
5838 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5839 ptr = mono_image_rva_map (method->klass->image, method_rva);
5840 flags = *(const unsigned char *) ptr;
5841 format = flags & METHOD_HEADER_FORMAT_MASK;
5843 case METHOD_HEADER_TINY_FORMAT:
5844 case METHOD_HEADER_TINY_FORMAT1:
5845 local_var_sig_token = 0;
5847 case METHOD_HEADER_FAT_FORMAT:
5851 local_var_sig_token = read32 (ptr);
5854 g_assert_not_reached ();
5857 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5859 ret->init_locals = header->init_locals;
5860 ret->max_stack = header->max_stack;
5861 ret->local_var_sig_token = local_var_sig_token;
5862 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5863 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5866 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5867 for (i = 0; i < header->num_locals; ++i) {
5868 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5869 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5870 info->is_pinned = header->locals [i]->pinned;
5871 info->local_index = i;
5872 mono_array_setref (ret->locals, i, info);
5876 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5877 for (i = 0; i < header->num_clauses; ++i) {
5878 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5879 MonoExceptionClause *clause = &header->clauses [i];
5881 info->flags = clause->flags;
5882 info->try_offset = clause->try_offset;
5883 info->try_length = clause->try_len;
5884 info->handler_offset = clause->handler_offset;
5885 info->handler_length = clause->handler_len;
5886 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5887 info->filter_offset = clause->data.filter_offset;
5888 else if (clause->data.catch_class)
5889 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5891 mono_array_setref (ret->clauses, i, info);
5894 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5899 mono_get_dbnull_object (MonoDomain *domain)
5903 static MonoClassField *dbnull_value_field = NULL;
5905 if (!dbnull_value_field) {
5906 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5907 mono_class_init (klass);
5908 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5909 g_assert (dbnull_value_field);
5911 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5918 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5920 guint32 param_index, i, lastp, crow = 0;
5921 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5924 MonoClass *klass = method->klass;
5925 MonoImage *image = klass->image;
5926 MonoMethodSignature *methodsig = mono_method_signature (method);
5928 MonoTableInfo *constt;
5929 MonoTableInfo *methodt;
5930 MonoTableInfo *paramt;
5932 if (!methodsig->param_count)
5935 mono_class_init (klass);
5937 if (klass->image->dynamic) {
5938 MonoReflectionMethodAux *aux;
5939 if (method->is_inflated)
5940 method = ((MonoMethodInflated*)method)->declaring;
5941 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5942 if (aux && aux->param_defaults) {
5943 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5944 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5949 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5950 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5951 constt = &image->tables [MONO_TABLE_CONSTANT];
5953 idx = mono_method_get_index (method) - 1;
5954 g_assert (idx != -1);
5956 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5957 if (idx + 1 < methodt->rows)
5958 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5960 lastp = paramt->rows + 1;
5962 for (i = param_index; i < lastp; ++i) {
5965 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5966 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5968 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5971 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5976 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5977 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5978 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5985 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5990 MonoType *basetype = type;
5995 klass = mono_class_from_mono_type (type);
5996 if (klass->valuetype) {
5997 object = mono_object_new (domain, klass);
5998 retval = ((gchar *) object + sizeof (MonoObject));
5999 if (klass->enumtype)
6000 basetype = klass->enum_basetype;
6005 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6012 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6016 memset (assembly, 0, sizeof (MonoAssemblyName));
6018 assembly->culture = "";
6019 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6021 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6024 while (g_ascii_isspace (*p) || *p == ',') {
6033 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6035 assembly->major = strtoul (p, &s, 10);
6036 if (s == p || *s != '.')
6039 assembly->minor = strtoul (p, &s, 10);
6040 if (s == p || *s != '.')
6043 assembly->build = strtoul (p, &s, 10);
6044 if (s == p || *s != '.')
6047 assembly->revision = strtoul (p, &s, 10);
6051 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6053 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6054 assembly->culture = "";
6057 assembly->culture = p;
6058 while (*p && *p != ',') {
6062 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6064 if (strncmp (p, "null", 4) == 0) {
6069 while (*p && *p != ',') {
6072 len = (p - start + 1);
6073 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6074 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6075 g_strlcpy (assembly->public_key_token, start, len);
6078 while (*p && *p != ',')
6082 while (g_ascii_isspace (*p) || *p == ',') {
6096 * mono_reflection_parse_type:
6099 * Parse a type name as accepted by the GetType () method and output the info
6100 * extracted in the info structure.
6101 * the name param will be mangled, so, make a copy before passing it to this function.
6102 * The fields in info will be valid until the memory pointed to by name is valid.
6104 * See also mono_type_get_name () below.
6106 * Returns: 0 on parse error.
6109 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6110 MonoTypeNameParse *info)
6112 char *start, *p, *w, *temp, *last_point, *startn;
6113 int in_modifiers = 0;
6114 int isbyref = 0, rank, arity = 0, i;
6116 start = p = w = name;
6118 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6119 info->name = info->name_space = NULL;
6120 info->nested = NULL;
6121 info->modifiers = NULL;
6122 info->type_arguments = NULL;
6124 /* last_point separates the namespace from the name */
6130 *p = 0; /* NULL terminate the name */
6132 info->nested = g_list_append (info->nested, startn);
6133 /* we have parsed the nesting namespace + name */
6137 info->name_space = start;
6139 info->name = last_point + 1;
6141 info->name_space = (char *)"";
6160 i = strtol (p, &temp, 10);
6177 info->name_space = start;
6179 info->name = last_point + 1;
6181 info->name_space = (char *)"";
6188 if (isbyref) /* only one level allowed by the spec */
6191 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6195 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6201 info->type_arguments = g_ptr_array_new ();
6202 for (i = 0; i < arity; i++) {
6203 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6204 gboolean fqname = FALSE;
6206 g_ptr_array_add (info->type_arguments, subinfo);
6213 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6224 while (*p && (*p != ']'))
6232 if (g_ascii_isspace (*aname)) {
6239 !assembly_name_to_aname (&subinfo->assembly, aname))
6243 if (i + 1 < arity) {
6263 else if (*p != '*') /* '*' means unknown lower bound */
6269 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6280 if (g_ascii_isspace (*p)) {
6287 return 0; /* missing assembly name */
6288 if (!assembly_name_to_aname (&info->assembly, p))
6294 if (info->assembly.name)
6297 // *w = 0; /* terminate class name */
6299 if (!info->name || !*info->name)
6303 /* add other consistency checks */
6308 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6310 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6314 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6316 gboolean type_resolve = FALSE;
6319 if (info->assembly.name) {
6320 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6322 /* then we must load the assembly ourselve - see #60439 */
6323 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6327 image = assembly->image;
6328 } else if (!image) {
6329 image = mono_defaults.corlib;
6332 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6333 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6334 image = mono_defaults.corlib;
6335 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6342 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6349 image = mono_defaults.corlib;
6352 klass = mono_class_from_name_case (image, info->name_space, info->name);
6354 klass = mono_class_from_name (image, info->name_space, info->name);
6357 for (mod = info->nested; mod; mod = mod->next) {
6360 mono_class_init (klass);
6361 nested = klass->nested_classes;
6364 klass = nested->data;
6366 if (g_strcasecmp (klass->name, mod->data) == 0)
6369 if (strcmp (klass->name, mod->data) == 0)
6373 nested = nested->next;
6380 mono_class_init (klass);
6382 if (info->type_arguments) {
6383 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6384 MonoReflectionType *the_type;
6388 for (i = 0; i < info->type_arguments->len; i++) {
6389 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6391 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6392 if (!type_args [i]) {
6398 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6400 instance = mono_reflection_bind_generic_parameters (
6401 the_type, info->type_arguments->len, type_args);
6408 klass = mono_class_from_mono_type (instance);
6411 for (mod = info->modifiers; mod; mod = mod->next) {
6412 modval = GPOINTER_TO_UINT (mod->data);
6413 if (!modval) { /* byref: must be last modifier */
6414 return &klass->this_arg;
6415 } else if (modval == -1) {
6416 klass = mono_ptr_class_get (&klass->byval_arg);
6417 } else { /* array rank */
6418 klass = mono_array_class_get (klass, modval);
6420 mono_class_init (klass);
6423 return &klass->byval_arg;
6427 * mono_reflection_get_type:
6428 * @image: a metadata context
6429 * @info: type description structure
6430 * @ignorecase: flag for case-insensitive string compares
6431 * @type_resolve: whenever type resolve was already tried
6433 * Build a MonoType from the type description in @info.
6438 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6441 MonoReflectionAssembly *assembly;
6445 type = mono_reflection_get_type_internal (image, info, ignorecase);
6448 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6455 *type_resolve = TRUE;
6458 /* Reconstruct the type name */
6459 fullName = g_string_new ("");
6460 if (info->name_space && (info->name_space [0] != '\0'))
6461 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6463 g_string_printf (fullName, info->name);
6464 for (mod = info->nested; mod; mod = mod->next)
6465 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6467 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6469 if (assembly->assembly->dynamic) {
6470 /* Enumerate all modules */
6471 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6475 if (abuilder->modules) {
6476 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6477 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6478 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6484 if (!type && abuilder->loaded_modules) {
6485 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6486 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6487 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6494 type = mono_reflection_get_type_internal (assembly->assembly->image,
6497 g_string_free (fullName, TRUE);
6502 free_type_info (MonoTypeNameParse *info)
6504 g_list_free (info->modifiers);
6505 g_list_free (info->nested);
6507 if (info->type_arguments) {
6510 for (i = 0; i < info->type_arguments->len; i++) {
6511 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6513 free_type_info (subinfo);
6516 g_ptr_array_free (info->type_arguments, TRUE);
6521 * mono_reflection_type_from_name:
6523 * @image: a metadata context (can be NULL).
6525 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6526 * it defaults to get the type from @image or, if @image is NULL or loading
6527 * from it fails, uses corlib.
6531 mono_reflection_type_from_name (char *name, MonoImage *image)
6533 MonoType *type = NULL;
6534 MonoTypeNameParse info;
6537 /* Make a copy since parse_type modifies its argument */
6538 tmp = g_strdup (name);
6540 /*g_print ("requested type %s\n", str);*/
6541 if (mono_reflection_parse_type (tmp, &info)) {
6542 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6546 free_type_info (&info);
6551 * mono_reflection_get_token:
6553 * Return the metadata token of OBJ which should be an object
6554 * representing a metadata element.
6557 mono_reflection_get_token (MonoObject *obj)
6562 klass = obj->vtable->klass;
6564 if (strcmp (klass->name, "MethodBuilder") == 0) {
6565 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6567 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6568 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6569 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6571 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6572 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6573 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6574 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6575 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6576 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6577 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6578 } else if (strcmp (klass->name, "MonoType") == 0) {
6579 MonoReflectionType *tb = (MonoReflectionType *)obj;
6580 token = mono_class_from_mono_type (tb->type)->type_token;
6581 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6582 strcmp (klass->name, "MonoMethod") == 0 ||
6583 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6584 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6585 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6586 if (m->method->is_inflated) {
6587 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6588 return inflated->declaring->token;
6590 token = m->method->token;
6592 } else if (strcmp (klass->name, "MonoField") == 0) {
6593 MonoReflectionField *f = (MonoReflectionField*)obj;
6595 if (f->field->generic_info && f->field->generic_info->reflection_info)
6596 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6598 token = mono_class_get_field_token (f->field);
6599 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6600 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6602 token = mono_class_get_property_token (p->property);
6603 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6604 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6606 token = mono_class_get_event_token (p->event);
6607 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6608 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6610 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6611 } else if (strcmp (klass->name, "Module") == 0) {
6612 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6615 } else if (strcmp (klass->name, "Assembly") == 0) {
6616 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6618 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6619 MonoException *ex = mono_get_exception_not_implemented (msg);
6621 mono_raise_exception (ex);
6628 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6630 int slen, type = t->type;
6631 MonoClass *tklass = t->data.klass;
6637 case MONO_TYPE_BOOLEAN: {
6638 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6643 case MONO_TYPE_CHAR:
6645 case MONO_TYPE_I2: {
6646 guint16 *val = g_malloc (sizeof (guint16));
6651 #if SIZEOF_VOID_P == 4
6657 case MONO_TYPE_I4: {
6658 guint32 *val = g_malloc (sizeof (guint32));
6663 #if SIZEOF_VOID_P == 8
6664 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6669 case MONO_TYPE_I8: {
6670 guint64 *val = g_malloc (sizeof (guint64));
6675 case MONO_TYPE_VALUETYPE:
6676 if (t->data.klass->enumtype) {
6677 type = t->data.klass->enum_basetype->type;
6680 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6683 case MONO_TYPE_STRING:
6684 if (*p == (char)0xFF) {
6688 slen = mono_metadata_decode_value (p, &p);
6690 return mono_string_new_len (mono_domain_get (), p, slen);
6691 case MONO_TYPE_CLASS: {
6694 if (*p == (char)0xFF) {
6699 slen = mono_metadata_decode_value (p, &p);
6700 n = g_memdup (p, slen + 1);
6702 t = mono_reflection_type_from_name (n, image);
6704 g_warning ("Cannot load type '%s'", n);
6708 return mono_type_get_object (mono_domain_get (), t);
6712 case MONO_TYPE_OBJECT: {
6715 MonoClass *subc = NULL;
6720 } else if (subt == 0x0E) {
6721 type = MONO_TYPE_STRING;
6723 } else if (subt == 0x1D) {
6724 MonoType simple_type = {{0}};
6728 type = MONO_TYPE_SZARRAY;
6729 simple_type.type = etype;
6730 tklass = mono_class_from_mono_type (&simple_type);
6732 } else if (subt == 0x55) {
6735 slen = mono_metadata_decode_value (p, &p);
6736 n = g_memdup (p, slen + 1);
6738 t = mono_reflection_type_from_name (n, image);
6740 g_error ("Cannot load type '%s'", n);
6743 subc = mono_class_from_mono_type (t);
6744 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6745 MonoType simple_type = {{0}};
6746 simple_type.type = subt;
6747 subc = mono_class_from_mono_type (&simple_type);
6749 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6751 val = load_cattr_value (image, &subc->byval_arg, p, end);
6752 obj = mono_object_new (mono_domain_get (), subc);
6753 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6757 case MONO_TYPE_SZARRAY: {
6759 guint32 i, alen, basetype;
6762 if (alen == 0xffffffff) {
6766 arr = mono_array_new (mono_domain_get(), tklass, alen);
6767 basetype = tklass->byval_arg.type;
6768 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
6769 basetype = tklass->enum_basetype->type;
6774 case MONO_TYPE_BOOLEAN:
6775 for (i = 0; i < alen; i++) {
6776 MonoBoolean val = *p++;
6777 mono_array_set (arr, MonoBoolean, i, val);
6780 case MONO_TYPE_CHAR:
6783 for (i = 0; i < alen; i++) {
6784 guint16 val = read16 (p);
6785 mono_array_set (arr, guint16, i, val);
6792 for (i = 0; i < alen; i++) {
6793 guint32 val = read32 (p);
6794 mono_array_set (arr, guint32, i, val);
6801 for (i = 0; i < alen; i++) {
6802 guint64 val = read64 (p);
6803 mono_array_set (arr, guint64, i, val);
6807 case MONO_TYPE_CLASS:
6808 case MONO_TYPE_OBJECT:
6809 case MONO_TYPE_STRING:
6810 for (i = 0; i < alen; i++) {
6811 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6812 mono_array_setref (arr, i, item);
6816 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
6822 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6828 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6830 static MonoClass *klass;
6831 static MonoMethod *ctor;
6833 void *params [2], *unboxed;
6836 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6838 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6840 params [0] = mono_type_get_object (mono_domain_get (), t);
6842 retval = mono_object_new (mono_domain_get (), klass);
6843 unboxed = mono_object_unbox (retval);
6844 mono_runtime_invoke (ctor, unboxed, params, NULL);
6850 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6852 static MonoClass *klass;
6853 static MonoMethod *ctor;
6855 void *unboxed, *params [2];
6858 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6860 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6863 params [1] = typedarg;
6864 retval = mono_object_new (mono_domain_get (), klass);
6865 unboxed = mono_object_unbox (retval);
6866 mono_runtime_invoke (ctor, unboxed, params, NULL);
6872 type_is_reference (MonoType *type)
6874 switch (type->type) {
6875 case MONO_TYPE_BOOLEAN:
6876 case MONO_TYPE_CHAR:
6889 case MONO_TYPE_VALUETYPE:
6897 free_param_data (MonoMethodSignature *sig, void **params) {
6899 for (i = 0; i < sig->param_count; ++i) {
6900 if (!type_is_reference (sig->params [i]))
6901 g_free (params [i]);
6906 * Find the field index in the metadata FieldDef table.
6909 find_field_index (MonoClass *klass, MonoClassField *field) {
6912 for (i = 0; i < klass->field.count; ++i) {
6913 if (field == &klass->fields [i])
6914 return klass->field.first + 1 + i;
6920 * Find the property index in the metadata Property table.
6923 find_property_index (MonoClass *klass, MonoProperty *property) {
6926 for (i = 0; i < klass->property.count; ++i) {
6927 if (property == &klass->properties [i])
6928 return klass->property.first + 1 + i;
6934 * Find the event index in the metadata Event table.
6937 find_event_index (MonoClass *klass, MonoEvent *event) {
6940 for (i = 0; i < klass->event.count; ++i) {
6941 if (event == &klass->events [i])
6942 return klass->event.first + 1 + i;
6948 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
6950 const char *p = (const char*)data;
6952 guint32 i, j, num_named;
6956 mono_class_init (method->klass);
6959 attr = mono_object_new (mono_domain_get (), method->klass);
6960 mono_runtime_invoke (method, attr, NULL, NULL);
6964 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6967 /*g_print ("got attr %s\n", method->klass->name);*/
6969 /* Allocate using alloca so it gets GC tracking */
6970 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6974 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6975 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6979 attr = mono_object_new (mono_domain_get (), method->klass);
6980 mono_runtime_invoke (method, attr, params, NULL);
6981 free_param_data (method->signature, params);
6982 num_named = read16 (named);
6984 for (j = 0; j < num_named; j++) {
6986 char *name, named_type, data_type;
6987 named_type = *named++;
6988 data_type = *named++; /* type of data */
6989 if (data_type == MONO_TYPE_SZARRAY)
6990 data_type = *named++;
6991 if (data_type == MONO_TYPE_ENUM) {
6994 type_len = mono_metadata_decode_blob_size (named, &named);
6995 type_name = g_malloc (type_len + 1);
6996 memcpy (type_name, named, type_len);
6997 type_name [type_len] = 0;
6999 /* FIXME: lookup the type and check type consistency */
7002 name_len = mono_metadata_decode_blob_size (named, &named);
7003 name = g_malloc (name_len + 1);
7004 memcpy (name, named, name_len);
7005 name [name_len] = 0;
7007 if (named_type == 0x53) {
7008 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7009 void *val = load_cattr_value (image, field->type, named, &named);
7010 mono_field_set_value (attr, field, val);
7011 if (!type_is_reference (field->type))
7013 } else if (named_type == 0x54) {
7016 MonoType *prop_type;
7018 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7019 /* can we have more that 1 arg in a custom attr named property? */
7020 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7021 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7022 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7023 mono_property_set_value (prop, attr, pparams, NULL);
7024 if (!type_is_reference (prop_type))
7025 g_free (pparams [0]);
7034 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7036 MonoArray *typedargs, *namedargs;
7037 MonoClass *attrklass;
7038 static MonoClass *klass;
7039 static MonoMethod *ctor;
7042 const char *p = (const char*)data;
7044 guint32 i, j, num_named;
7047 mono_class_init (method->klass);
7050 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7052 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
7054 domain = mono_domain_get ();
7056 /* This is for Attributes with no parameters */
7057 attr = mono_object_new (domain, klass);
7058 params [0] = mono_method_get_object (domain, method, NULL);
7059 params [1] = params [2] = NULL;
7060 mono_runtime_invoke (method, attr, params, NULL);
7064 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7067 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7071 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7072 MonoObject *obj, *typedarg;
7075 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7076 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7077 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7078 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7079 mono_array_setref (typedargs, i, typedarg);
7081 if (!type_is_reference (mono_method_signature (method)->params [i]))
7086 num_named = read16 (named);
7087 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7089 attrklass = method->klass;
7090 for (j = 0; j < num_named; j++) {
7092 char *name, named_type, data_type;
7093 named_type = *named++;
7094 data_type = *named++; /* type of data */
7095 if (data_type == MONO_TYPE_SZARRAY)
7096 data_type = *named++;
7097 if (data_type == MONO_TYPE_ENUM) {
7100 type_len = mono_metadata_decode_blob_size (named, &named);
7101 type_name = g_malloc (type_len + 1);
7102 memcpy (type_name, named, type_len);
7103 type_name [type_len] = 0;
7105 /* FIXME: lookup the type and check type consistency */
7108 name_len = mono_metadata_decode_blob_size (named, &named);
7109 name = g_malloc (name_len + 1);
7110 memcpy (name, named, name_len);
7111 name [name_len] = 0;
7113 if (named_type == 0x53) {
7114 MonoObject *obj, *typedarg, *namedarg;
7115 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7116 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7118 minfo = mono_field_get_object (domain, NULL, field);
7119 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7120 typedarg = create_cattr_typed_arg (field->type, obj);
7121 namedarg = create_cattr_named_arg (minfo, typedarg);
7122 mono_array_setref (namedargs, j, namedarg);
7123 if (!type_is_reference (field->type))
7125 } else if (named_type == 0x54) {
7126 MonoObject *obj, *typedarg, *namedarg;
7127 MonoType *prop_type;
7129 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7131 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7132 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7133 minfo = mono_property_get_object (domain, NULL, prop);
7134 val = load_cattr_value (image, prop_type, named, &named);
7135 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7136 typedarg = create_cattr_typed_arg (prop_type, obj);
7137 namedarg = create_cattr_named_arg (minfo, typedarg);
7138 mono_array_setref (namedargs, j, namedarg);
7139 if (!type_is_reference (prop_type))
7144 attr = mono_object_new (domain, klass);
7145 params [0] = mono_method_get_object (domain, method, NULL);
7146 params [1] = typedargs;
7147 params [2] = namedargs;
7148 mono_runtime_invoke (ctor, attr, params, NULL);
7153 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7160 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7161 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7162 for (i = 0; i < cinfo->num_attrs; ++i) {
7163 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7164 mono_array_setref (result, i, attr);
7170 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7178 for (i = 0; i < cinfo->num_attrs; ++i) {
7179 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7183 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7184 result = mono_array_new (mono_domain_get (), klass, n);
7186 for (i = 0; i < cinfo->num_attrs; ++i) {
7187 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7188 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7189 mono_array_setref (result, n, attr);
7197 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7200 static MonoClass *klass;
7205 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7207 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7208 for (i = 0; i < cinfo->num_attrs; ++i) {
7209 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7210 mono_array_setref (result, i, attr);
7216 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7218 guint32 mtoken, i, len;
7219 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7221 MonoCustomAttrInfo *ainfo;
7222 GList *tmp, *list = NULL;
7225 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7227 i = mono_metadata_custom_attrs_from_index (image, idx);
7231 while (i < ca->rows) {
7232 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7234 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7237 len = g_list_length (list);
7240 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7241 ainfo->num_attrs = len;
7242 ainfo->image = image;
7243 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7244 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7245 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7246 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7247 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7248 mtoken |= MONO_TOKEN_METHOD_DEF;
7250 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7251 mtoken |= MONO_TOKEN_MEMBER_REF;
7254 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7257 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7258 if (!ainfo->attrs [i].ctor)
7259 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7260 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7261 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7262 ainfo->attrs [i].data = (guchar*)data;
7270 mono_custom_attrs_from_method (MonoMethod *method)
7272 MonoCustomAttrInfo *cinfo;
7275 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7277 idx = mono_method_get_index (method);
7278 idx <<= MONO_CUSTOM_ATTR_BITS;
7279 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7280 return mono_custom_attrs_from_index (method->klass->image, idx);
7284 mono_custom_attrs_from_class (MonoClass *klass)
7286 MonoCustomAttrInfo *cinfo;
7289 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7291 idx = mono_metadata_token_index (klass->type_token);
7292 idx <<= MONO_CUSTOM_ATTR_BITS;
7293 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7294 return mono_custom_attrs_from_index (klass->image, idx);
7298 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7300 MonoCustomAttrInfo *cinfo;
7303 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7305 idx = 1; /* there is only one assembly */
7306 idx <<= MONO_CUSTOM_ATTR_BITS;
7307 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7308 return mono_custom_attrs_from_index (assembly->image, idx);
7311 static MonoCustomAttrInfo*
7312 mono_custom_attrs_from_module (MonoImage *image)
7314 MonoCustomAttrInfo *cinfo;
7317 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7319 idx = 1; /* there is only one module */
7320 idx <<= MONO_CUSTOM_ATTR_BITS;
7321 idx |= MONO_CUSTOM_ATTR_MODULE;
7322 return mono_custom_attrs_from_index (image, idx);
7326 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7328 MonoCustomAttrInfo *cinfo;
7331 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7333 idx = find_property_index (klass, property);
7334 idx <<= MONO_CUSTOM_ATTR_BITS;
7335 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7336 return mono_custom_attrs_from_index (klass->image, idx);
7340 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7342 MonoCustomAttrInfo *cinfo;
7345 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7347 idx = find_event_index (klass, event);
7348 idx <<= MONO_CUSTOM_ATTR_BITS;
7349 idx |= MONO_CUSTOM_ATTR_EVENT;
7350 return mono_custom_attrs_from_index (klass->image, idx);
7354 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7356 MonoCustomAttrInfo *cinfo;
7359 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7361 idx = find_field_index (klass, field);
7362 idx <<= MONO_CUSTOM_ATTR_BITS;
7363 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7364 return mono_custom_attrs_from_index (klass->image, idx);
7368 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7371 guint32 i, idx, method_index;
7372 guint32 param_list, param_last, param_pos, found;
7374 MonoReflectionMethodAux *aux;
7376 if (method->klass->image->dynamic) {
7377 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7378 if (!aux || !aux->param_cattr)
7380 return aux->param_cattr [param];
7383 image = method->klass->image;
7384 method_index = mono_method_get_index (method);
7385 ca = &image->tables [MONO_TABLE_METHOD];
7387 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7388 if (method_index == ca->rows) {
7389 ca = &image->tables [MONO_TABLE_PARAM];
7390 param_last = ca->rows + 1;
7392 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7393 ca = &image->tables [MONO_TABLE_PARAM];
7396 for (i = param_list; i < param_last; ++i) {
7397 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7398 if (param_pos == param) {
7406 idx <<= MONO_CUSTOM_ATTR_BITS;
7407 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7408 return mono_custom_attrs_from_index (image, idx);
7412 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7416 for (i = 0; i < ainfo->num_attrs; ++i) {
7417 klass = ainfo->attrs [i].ctor->klass;
7418 if (mono_class_has_parent (klass, attr_klass))
7425 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7432 for (i = 0; i < ainfo->num_attrs; ++i) {
7433 klass = ainfo->attrs [i].ctor->klass;
7434 if (mono_class_has_parent (klass, attr_klass)) {
7439 if (attr_index == -1)
7442 attrs = mono_custom_attrs_construct (ainfo);
7444 return mono_array_get (attrs, MonoObject*, attr_index);
7450 * mono_reflection_get_custom_attrs_info:
7451 * @obj: a reflection object handle
7453 * Return the custom attribute info for attributes defined for the
7454 * reflection handle @obj. The objects.
7457 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7460 MonoCustomAttrInfo *cinfo = NULL;
7462 klass = obj->vtable->klass;
7463 if (klass == mono_defaults.monotype_class) {
7464 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7465 klass = mono_class_from_mono_type (rtype->type);
7466 cinfo = mono_custom_attrs_from_class (klass);
7467 } else if (strcmp ("Assembly", klass->name) == 0) {
7468 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7469 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7470 } else if (strcmp ("Module", klass->name) == 0) {
7471 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7472 cinfo = mono_custom_attrs_from_module (module->image);
7473 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7474 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7475 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7476 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7477 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7478 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7479 } else if (strcmp ("MonoField", klass->name) == 0) {
7480 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7481 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7482 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7483 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7484 cinfo = mono_custom_attrs_from_method (rmethod->method);
7485 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7486 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7487 cinfo = mono_custom_attrs_from_method (method);
7488 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7489 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7490 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7491 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7492 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7493 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7494 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7495 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7496 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7497 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7498 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7499 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7500 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7501 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7502 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7503 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7504 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7505 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7506 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7507 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7508 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7509 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7510 } else { /* handle other types here... */
7511 g_error ("get custom attrs not yet supported for %s", klass->name);
7518 * mono_reflection_get_custom_attrs_by_type:
7519 * @obj: a reflection object handle
7521 * Return an array with all the custom attributes defined of the
7522 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7523 * of that type are returned. The objects are fully build.
7526 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7529 MonoCustomAttrInfo *cinfo;
7531 cinfo = mono_reflection_get_custom_attrs_info (obj);
7534 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7536 result = mono_custom_attrs_construct (cinfo);
7538 mono_custom_attrs_free (cinfo);
7541 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7542 result = mono_array_new (mono_domain_get (), klass, 0);
7549 * mono_reflection_get_custom_attrs:
7550 * @obj: a reflection object handle
7552 * Return an array with all the custom attributes defined of the
7553 * reflection handle @obj. The objects are fully build.
7556 mono_reflection_get_custom_attrs (MonoObject *obj)
7558 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7562 * mono_reflection_get_custom_attrs_data:
7563 * @obj: a reflection obj handle
7565 * Returns an array of System.Reflection.CustomAttributeData,
7566 * which include information about attributes reflected on
7567 * types loaded using the Reflection Only methods
7570 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7573 MonoCustomAttrInfo *cinfo;
7575 cinfo = mono_reflection_get_custom_attrs_info (obj);
7577 result = mono_custom_attrs_data_construct (cinfo);
7579 mono_custom_attrs_free (cinfo);
7582 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7583 result = mono_array_new (mono_domain_get (), klass, 0);
7590 * LOCKING: Assumes the loader lock is held.
7592 static MonoMethodSignature*
7593 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7594 MonoMethodSignature *sig;
7597 count = parameters? mono_array_length (parameters): 0;
7599 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7600 sig->param_count = count;
7601 sig->sentinelpos = -1; /* FIXME */
7602 for (i = 0; i < count; ++i) {
7603 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7604 sig->params [i] = pt->type;
7610 * LOCKING: Assumes the loader lock is held.
7612 static MonoMethodSignature*
7613 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7614 MonoMethodSignature *sig;
7616 sig = parameters_to_signature (mp, ctor->parameters);
7617 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7618 sig->ret = &mono_defaults.void_class->byval_arg;
7623 * LOCKING: Assumes the loader lock is held.
7625 static MonoMethodSignature*
7626 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7627 MonoMethodSignature *sig;
7629 sig = parameters_to_signature (mp, method->parameters);
7630 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7631 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7632 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7636 static MonoMethodSignature*
7637 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7638 MonoMethodSignature *sig;
7640 sig = parameters_to_signature (NULL, method->parameters);
7641 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7642 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7643 sig->generic_param_count = 0;
7648 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7650 MonoClass *klass = mono_object_class (prop);
7651 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7652 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7653 *name = mono_string_to_utf8 (pb->name);
7654 *type = pb->type->type;
7656 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7657 *name = g_strdup (p->property->name);
7658 if (p->property->get)
7659 *type = mono_method_signature (p->property->get)->ret;
7661 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7666 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7668 MonoClass *klass = mono_object_class (field);
7669 if (strcmp (klass->name, "FieldBuilder") == 0) {
7670 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7671 *name = mono_string_to_utf8 (fb->name);
7672 *type = fb->type->type;
7674 MonoReflectionField *f = (MonoReflectionField *)field;
7675 *name = g_strdup (f->field->name);
7676 *type = f->field->type;
7681 * Encode a value in a custom attribute stream of bytes.
7682 * The value to encode is either supplied as an object in argument val
7683 * (valuetypes are boxed), or as a pointer to the data in the
7685 * @type represents the type of the value
7686 * @buffer is the start of the buffer
7687 * @p the current position in the buffer
7688 * @buflen contains the size of the buffer and is used to return the new buffer size
7689 * if this needs to be realloced.
7690 * @retbuffer and @retp return the start and the position of the buffer
7693 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7695 MonoTypeEnum simple_type;
7697 if ((p-buffer) + 10 >= *buflen) {
7700 newbuf = g_realloc (buffer, *buflen);
7701 p = newbuf + (p-buffer);
7705 argval = ((char*)arg + sizeof (MonoObject));
7706 simple_type = type->type;
7708 switch (simple_type) {
7709 case MONO_TYPE_BOOLEAN:
7714 case MONO_TYPE_CHAR:
7717 swap_with_size (p, argval, 2, 1);
7723 swap_with_size (p, argval, 4, 1);
7729 swap_with_size (p, argval, 8, 1);
7732 case MONO_TYPE_VALUETYPE:
7733 if (type->data.klass->enumtype) {
7734 simple_type = type->data.klass->enum_basetype->type;
7737 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7740 case MONO_TYPE_STRING: {
7747 str = mono_string_to_utf8 ((MonoString*)arg);
7748 slen = strlen (str);
7749 if ((p-buffer) + 10 + slen >= *buflen) {
7753 newbuf = g_realloc (buffer, *buflen);
7754 p = newbuf + (p-buffer);
7757 mono_metadata_encode_value (slen, p, &p);
7758 memcpy (p, str, slen);
7763 case MONO_TYPE_CLASS: {
7771 k = mono_object_class (arg);
7772 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7773 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7774 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
7776 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7777 slen = strlen (str);
7778 if ((p-buffer) + 10 + slen >= *buflen) {
7782 newbuf = g_realloc (buffer, *buflen);
7783 p = newbuf + (p-buffer);
7786 mono_metadata_encode_value (slen, p, &p);
7787 memcpy (p, str, slen);
7792 case MONO_TYPE_SZARRAY: {
7794 MonoClass *eclass, *arg_eclass;
7797 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7800 len = mono_array_length ((MonoArray*)arg);
7802 *p++ = (len >> 8) & 0xff;
7803 *p++ = (len >> 16) & 0xff;
7804 *p++ = (len >> 24) & 0xff;
7806 *retbuffer = buffer;
7807 eclass = type->data.klass;
7808 arg_eclass = mono_object_class (arg)->element_class;
7811 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7812 eclass = mono_defaults.object_class;
7814 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7815 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7816 int elsize = mono_class_array_element_size (arg_eclass);
7817 for (i = 0; i < len; ++i) {
7818 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7821 } else if (eclass->valuetype && arg_eclass->valuetype) {
7822 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7823 int elsize = mono_class_array_element_size (eclass);
7824 for (i = 0; i < len; ++i) {
7825 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7829 for (i = 0; i < len; ++i) {
7830 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7835 case MONO_TYPE_OBJECT: {
7841 * The parameter type is 'object' but the type of the actual
7842 * argument is not. So we have to add type information to the blob
7843 * too. This is completely undocumented in the spec.
7847 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7852 klass = mono_object_class (arg);
7854 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7857 } else if (klass->enumtype) {
7859 } else if (klass == mono_defaults.string_class) {
7860 simple_type = MONO_TYPE_STRING;
7863 } else if (klass->rank == 1) {
7865 *p++ = klass->element_class->byval_arg.type;
7866 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
7868 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7869 *p++ = simple_type = klass->byval_arg.type;
7872 g_error ("unhandled type in custom attr");
7874 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7875 slen = strlen (str);
7876 if ((p-buffer) + 10 + slen >= *buflen) {
7880 newbuf = g_realloc (buffer, *buflen);
7881 p = newbuf + (p-buffer);
7884 mono_metadata_encode_value (slen, p, &p);
7885 memcpy (p, str, slen);
7888 simple_type = klass->enum_basetype->type;
7892 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7895 *retbuffer = buffer;
7899 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
7901 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7902 char *str = type_get_qualified_name (type, NULL);
7903 int slen = strlen (str);
7907 * This seems to be optional...
7910 mono_metadata_encode_value (slen, p, &p);
7911 memcpy (p, str, slen);
7914 } else if (type->type == MONO_TYPE_OBJECT) {
7916 } else if (type->type == MONO_TYPE_CLASS) {
7917 /* it should be a type: encode_cattr_value () has the check */
7920 mono_metadata_encode_value (type->type, p, &p);
7921 if (type->type == MONO_TYPE_SZARRAY)
7922 /* See the examples in Partition VI, Annex B */
7923 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
7930 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7933 /* Preallocate a large enough buffer */
7934 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7935 char *str = type_get_qualified_name (type, NULL);
7938 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
7939 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
7945 len += strlen (name);
7947 if ((p-buffer) + 20 + len >= *buflen) {
7951 newbuf = g_realloc (buffer, *buflen);
7952 p = newbuf + (p-buffer);
7956 encode_field_or_prop_type (type, p, &p);
7958 len = strlen (name);
7959 mono_metadata_encode_value (len, p, &p);
7960 memcpy (p, name, len);
7962 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7964 *retbuffer = buffer;
7968 * mono_reflection_get_custom_attrs_blob:
7969 * @ctor: custom attribute constructor
7970 * @ctorArgs: arguments o the constructor
7976 * Creates the blob of data that needs to be saved in the metadata and that represents
7977 * the custom attributed described by @ctor, @ctorArgs etc.
7978 * Returns: a Byte array representing the blob of data.
7981 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7984 MonoMethodSignature *sig;
7989 MONO_ARCH_SAVE_REGS;
7991 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7992 /* sig is freed later so allocate it in the heap */
7993 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
7995 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7998 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8000 p = buffer = g_malloc (buflen);
8001 /* write the prolog */
8004 for (i = 0; i < sig->param_count; ++i) {
8005 arg = mono_array_get (ctorArgs, MonoObject*, i);
8006 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8010 i += mono_array_length (properties);
8012 i += mono_array_length (fields);
8014 *p++ = (i >> 8) & 0xff;
8017 for (i = 0; i < mono_array_length (properties); ++i) {
8021 prop = mono_array_get (properties, gpointer, i);
8022 get_prop_name_and_type (prop, &pname, &ptype);
8023 *p++ = 0x54; /* PROPERTY signature */
8024 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8031 for (i = 0; i < mono_array_length (fields); ++i) {
8035 field = mono_array_get (fields, gpointer, i);
8036 get_field_name_and_type (field, &fname, &ftype);
8037 *p++ = 0x53; /* FIELD signature */
8038 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8043 g_assert (p - buffer <= buflen);
8044 buflen = p - buffer;
8045 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8046 p = mono_array_addr (result, char, 0);
8047 memcpy (p, buffer, buflen);
8049 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8055 static void* reflection_info_desc = NULL;
8056 #define MOVING_GC_REGISTER(addr) do { \
8057 if (!reflection_info_desc) { \
8059 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8061 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8064 #define MOVING_GC_REGISTER(addr)
8068 * mono_reflection_setup_internal_class:
8069 * @tb: a TypeBuilder object
8071 * Creates a MonoClass that represents the TypeBuilder.
8072 * This is a trick that lets us simplify a lot of reflection code
8073 * (and will allow us to support Build and Run assemblies easier).
8076 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8078 MonoClass *klass, *parent;
8080 MONO_ARCH_SAVE_REGS;
8082 mono_loader_lock ();
8085 /* check so we can compile corlib correctly */
8086 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8087 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8088 parent = tb->parent->type->data.klass;
8090 parent = my_mono_class_from_mono_type (tb->parent->type);
8096 /* the type has already being created: it means we just have to change the parent */
8097 if (tb->type.type) {
8098 klass = mono_class_from_mono_type (tb->type.type);
8099 klass->parent = NULL;
8100 /* fool mono_class_setup_parent */
8101 klass->supertypes = NULL;
8102 mono_class_setup_parent (klass, parent);
8103 mono_class_setup_mono_type (klass);
8104 mono_loader_unlock ();
8108 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8110 klass->image = &tb->module->dynamic_image->image;
8112 klass->inited = 1; /* we lie to the runtime */
8113 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8114 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8115 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8116 klass->flags = tb->attrs;
8118 klass->element_class = klass;
8120 MOVING_GC_REGISTER (&klass->reflection_info);
8121 klass->reflection_info = tb;
8123 /* Put into cache so mono_class_get () will find it */
8124 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8126 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8127 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8129 if (parent != NULL) {
8130 mono_class_setup_parent (klass, parent);
8131 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8132 const char *old_n = klass->name;
8133 /* trick to get relative numbering right when compiling corlib */
8134 klass->name = "BuildingObject";
8135 mono_class_setup_parent (klass, mono_defaults.object_class);
8136 klass->name = old_n;
8139 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8140 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8141 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8142 klass->instance_size = sizeof (MonoObject);
8143 klass->size_inited = 1;
8144 mono_class_setup_vtable_general (klass, NULL, 0);
8147 mono_class_setup_mono_type (klass);
8149 mono_class_setup_supertypes (klass);
8152 * FIXME: handle interfaces.
8155 tb->type.type = &klass->byval_arg;
8157 if (tb->nesting_type) {
8158 g_assert (tb->nesting_type->type);
8159 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8162 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8164 mono_loader_unlock ();
8168 * mono_reflection_setup_generic_class:
8169 * @tb: a TypeBuilder object
8171 * Setup the generic class before adding the first generic parameter.
8174 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8178 MONO_ARCH_SAVE_REGS;
8180 klass = my_mono_class_from_mono_type (tb->type.type);
8181 if (tb->generic_container)
8184 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8185 tb->generic_container->klass = klass;
8189 * mono_reflection_create_generic_class:
8190 * @tb: a TypeBuilder object
8192 * Creates the generic class after all generic parameters have been added.
8195 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8200 MONO_ARCH_SAVE_REGS;
8202 klass = my_mono_class_from_mono_type (tb->type.type);
8204 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8206 if (klass->generic_container || (count == 0))
8209 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
8211 klass->generic_container = tb->generic_container;
8213 klass->generic_container->type_argc = count;
8214 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8216 for (i = 0; i < count; i++) {
8217 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8218 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8219 g_assert (klass->generic_container->type_params [i].owner);
8222 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8226 * mono_reflection_create_internal_class:
8227 * @tb: a TypeBuilder object
8229 * Actually create the MonoClass that is associated with the TypeBuilder.
8232 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8236 MONO_ARCH_SAVE_REGS;
8238 klass = my_mono_class_from_mono_type (tb->type.type);
8240 mono_loader_lock ();
8241 if (klass->enumtype && klass->enum_basetype == NULL) {
8242 MonoReflectionFieldBuilder *fb;
8245 g_assert (tb->fields != NULL);
8246 g_assert (mono_array_length (tb->fields) >= 1);
8248 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8250 klass->enum_basetype = fb->type->type;
8251 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8252 if (!klass->element_class)
8253 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8256 * get the element_class from the current corlib.
8258 ec = default_class_from_mono_type (klass->enum_basetype);
8259 klass->instance_size = ec->instance_size;
8260 klass->size_inited = 1;
8262 * this is almost safe to do with enums and it's needed to be able
8263 * to create objects of the enum type (for use in SetConstant).
8265 /* FIXME: Does this mean enums can't have method overrides ? */
8266 mono_class_setup_vtable_general (klass, NULL, 0);
8268 mono_loader_unlock ();
8271 static MonoMarshalSpec*
8272 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8273 MonoReflectionMarshal *minfo)
8275 MonoMarshalSpec *res;
8277 res = g_new0 (MonoMarshalSpec, 1);
8278 res->native = minfo->type;
8280 switch (minfo->type) {
8281 case MONO_NATIVE_LPARRAY:
8282 res->data.array_data.elem_type = minfo->eltype;
8283 if (minfo->has_size) {
8284 res->data.array_data.param_num = minfo->param_num;
8285 res->data.array_data.num_elem = minfo->count;
8286 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8289 res->data.array_data.param_num = -1;
8290 res->data.array_data.num_elem = -1;
8291 res->data.array_data.elem_mult = -1;
8295 case MONO_NATIVE_BYVALTSTR:
8296 case MONO_NATIVE_BYVALARRAY:
8297 res->data.array_data.num_elem = minfo->count;
8300 case MONO_NATIVE_CUSTOM:
8301 if (minfo->marshaltyperef)
8302 res->data.custom_data.custom_name =
8303 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8305 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8315 MonoReflectionMarshal*
8316 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8317 MonoMarshalSpec *spec)
8319 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8320 MonoReflectionMarshal *minfo;
8323 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8324 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8325 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8326 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8329 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8330 minfo->type = spec->native;
8332 switch (minfo->type) {
8333 case MONO_NATIVE_LPARRAY:
8334 minfo->eltype = spec->data.array_data.elem_type;
8335 minfo->count = spec->data.array_data.num_elem;
8336 minfo->param_num = spec->data.array_data.param_num;
8339 case MONO_NATIVE_BYVALTSTR:
8340 case MONO_NATIVE_BYVALARRAY:
8341 minfo->count = spec->data.array_data.num_elem;
8344 case MONO_NATIVE_CUSTOM:
8345 if (spec->data.custom_data.custom_name) {
8346 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8348 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8350 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8352 if (spec->data.custom_data.cookie)
8353 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8364 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8365 ReflectionMethodBuilder *rmb,
8366 MonoMethodSignature *sig)
8369 MonoMethodNormal *pm;
8370 MonoMarshalSpec **specs;
8371 MonoReflectionMethodAux *method_aux;
8376 g_assert (!klass->generic_class);
8379 * Methods created using a MethodBuilder should have their memory allocated
8380 * inside the image mempool, while dynamic methods should have their memory
8383 dynamic = rmb->refs != NULL;
8384 mp = dynamic ? NULL : klass->image->mempool;
8386 mono_loader_lock ();
8388 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8389 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8390 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8392 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8394 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8396 pm = (MonoMethodNormal*)m;
8399 m->flags = rmb->attrs;
8400 m->iflags = rmb->iattrs;
8401 m->name = dynamic ? mono_string_to_utf8 (rmb->name) : mono_string_to_utf8_mp (mp, rmb->name);
8404 m->skip_visibility = rmb->skip_visibility;
8406 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8408 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8409 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8412 m->signature->pinvoke = 1;
8413 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8414 m->signature->pinvoke = 1;
8416 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8418 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8419 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8421 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8423 if (klass->image->dynamic)
8424 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8426 mono_loader_unlock ();
8429 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8430 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8431 MonoMethodHeader *header;
8433 gint32 max_stack, i;
8434 gint32 num_locals = 0;
8435 gint32 num_clauses = 0;
8439 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8440 code_size = rmb->ilgen->code_len;
8441 max_stack = rmb->ilgen->max_stack;
8442 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8443 if (rmb->ilgen->ex_handlers)
8444 num_clauses = method_count_clauses (rmb->ilgen);
8447 code = mono_array_addr (rmb->code, guint8, 0);
8448 code_size = mono_array_length (rmb->code);
8449 /* we probably need to run a verifier on the code... */
8459 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8460 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8461 header->code_size = code_size;
8462 header->code = mp_g_malloc (mp, code_size);
8463 memcpy ((char*)header->code, code, code_size);
8464 header->max_stack = max_stack;
8465 header->init_locals = rmb->init_locals;
8466 header->num_locals = num_locals;
8468 for (i = 0; i < num_locals; ++i) {
8469 MonoReflectionLocalBuilder *lb =
8470 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8472 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8473 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8476 header->num_clauses = num_clauses;
8478 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8479 rmb->ilgen, num_clauses);
8482 pm->header = header;
8485 if (rmb->generic_params) {
8486 int count = mono_array_length (rmb->generic_params);
8487 MonoGenericContainer *container;
8489 m->generic_container = container = rmb->generic_container;
8490 container->type_argc = count;
8491 container->type_params = g_new0 (MonoGenericParam, count);
8493 for (i = 0; i < count; i++) {
8494 MonoReflectionGenericParam *gp =
8495 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8497 container->type_params [i] = *gp->type.type->data.generic_param;
8498 container->type_params [i].method = m;
8501 if (klass->generic_container) {
8502 container->parent = klass->generic_container;
8503 container->context.class_inst = klass->generic_container->context.class_inst;
8505 container->context.gmethod = mono_get_shared_generic_method (container);
8509 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8513 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8515 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8516 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8517 for (i = 0; i < rmb->nrefs; ++i)
8518 data [i + 1] = rmb->refs [i];
8523 /* Parameter info */
8526 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8527 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8528 for (i = 0; i <= m->signature->param_count; ++i) {
8529 MonoReflectionParamBuilder *pb;
8530 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8531 if ((i > 0) && (pb->attrs)) {
8532 /* Make a copy since it might point to a shared type structure */
8533 /* FIXME: Alloc this from a mempool */
8534 m->signature->params [i - 1] = g_memdup (m->signature->params [i - 1], sizeof (MonoType) + ((m->signature->params [i - 1]->num_mods - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod)));
8535 m->signature->params [i - 1]->attrs = pb->attrs;
8538 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8539 MonoDynamicImage *assembly;
8540 guint32 idx, def_type, len;
8544 if (!method_aux->param_defaults) {
8545 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8546 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8548 assembly = (MonoDynamicImage*)klass->image;
8549 idx = encode_constant (assembly, pb->def_value, &def_type);
8550 /* Copy the data from the blob since it might get realloc-ed */
8551 p = assembly->blob.data + idx;
8552 len = mono_metadata_decode_blob_size (p, &p2);
8554 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8555 method_aux->param_default_types [i] = def_type;
8556 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8560 method_aux->param_names [i] = dynamic ? mono_string_to_utf8 (pb->name) : mono_string_to_utf8_mp (mp, pb->name);
8562 if (!method_aux->param_cattr)
8563 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8564 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8570 /* Parameter marshalling */
8573 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8574 MonoReflectionParamBuilder *pb;
8575 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8576 if (pb->marshal_info) {
8578 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8579 specs [pb->position] =
8580 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8584 if (specs != NULL) {
8586 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8587 method_aux->param_marshall = specs;
8590 if (klass->image->dynamic && method_aux)
8591 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8593 mono_loader_unlock ();
8599 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8601 ReflectionMethodBuilder rmb;
8602 MonoMethodSignature *sig;
8604 mono_loader_lock ();
8605 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8606 mono_loader_unlock ();
8608 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8610 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8611 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8613 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8614 /* ilgen is no longer needed */
8622 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8624 ReflectionMethodBuilder rmb;
8625 MonoMethodSignature *sig;
8627 mono_loader_lock ();
8628 sig = method_builder_to_signature (klass->image->mempool, mb);
8629 mono_loader_unlock ();
8631 reflection_methodbuilder_from_method_builder (&rmb, mb);
8633 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8634 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8636 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8637 /* ilgen is no longer needed */
8643 static MonoClassField*
8644 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8646 MonoClassField *field;
8650 field = g_new0 (MonoClassField, 1);
8652 field->name = mono_string_to_utf8 (fb->name);
8654 /* FIXME: handle type modifiers */
8655 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8656 field->type->attrs = fb->attrs;
8658 field->type = fb->type->type;
8660 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8661 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8662 if (fb->offset != -1)
8663 field->offset = fb->offset;
8664 field->parent = klass;
8665 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8667 if (fb->def_value) {
8668 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8669 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8670 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8671 /* Copy the data from the blob since it might get realloc-ed */
8672 p = assembly->blob.data + idx;
8673 len = mono_metadata_decode_blob_size (p, &p2);
8675 field->data = g_malloc (len);
8676 memcpy ((gpointer)field->data, p, len);
8683 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8686 MonoReflectionTypeBuilder *tb = NULL;
8687 MonoGenericClass *gclass, *cached;
8688 gboolean is_dynamic = FALSE;
8693 mono_loader_lock ();
8695 domain = mono_object_domain (type);
8697 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8698 tb = (MonoReflectionTypeBuilder *) type;
8701 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8702 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8703 MonoReflectionType *rgt = rgi->generic_type;
8705 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8706 tb = (MonoReflectionTypeBuilder *) rgt;
8711 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
8712 if (tb && tb->generic_container)
8713 mono_reflection_create_generic_class (tb);
8715 klass = mono_class_from_mono_type (type->type);
8716 if (!klass->generic_container) {
8717 mono_loader_unlock ();
8721 if (klass->wastypebuilder) {
8722 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8728 MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
8729 gclass = &dgclass->generic_class;
8730 gclass->is_dynamic = TRUE;
8732 gclass = g_new0 (MonoGenericClass, 1);
8735 gclass->inst = g_new0 (MonoGenericInst, 1);
8737 gclass->inst->type_argc = type_argc;
8738 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8739 gclass->inst->is_reference = 1;
8741 for (i = 0; i < gclass->inst->type_argc; ++i) {
8742 MonoType *t = dup_type (types [i]);
8744 if (!gclass->inst->is_open)
8745 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8746 if (gclass->inst->is_reference)
8747 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8748 gclass->inst->type_argv [i] = t;
8751 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8753 gclass->container_class = klass;
8755 geninst = g_new0 (MonoType, 1);
8756 geninst->type = MONO_TYPE_GENERICINST;
8758 cached = mono_metadata_lookup_generic_class (gclass);
8761 mono_loader_unlock ();
8762 geninst->data.generic_class = cached;
8766 geninst->data.generic_class = gclass;
8768 mono_loader_unlock ();
8774 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8777 MonoGenericClass *gclass, *cached;
8781 klass = mono_class_from_mono_type (type);
8782 if (!klass->generic_container && !klass->generic_class &&
8783 !(klass->nested_in && klass->nested_in->generic_container))
8786 mono_loader_lock ();
8788 gclass = g_new0 (MonoGenericClass, 1);
8790 gclass->inst = g_new0 (MonoGenericInst, 1);
8791 gclass->inst->type_argc = type_argc;
8792 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8793 gclass->inst->is_reference = 1;
8795 for (i = 0; i < gclass->inst->type_argc; ++i) {
8796 MonoType *t = dup_type (types [i]);
8798 if (!gclass->inst->is_open)
8799 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8800 if (gclass->inst->is_reference)
8801 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8803 gclass->inst->type_argv [i] = t;
8806 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8808 gclass->container_class = klass;
8810 if (klass->generic_class) {
8811 MonoGenericClass *kgclass = klass->generic_class;
8812 MonoGenericClass *ogclass = gclass;
8814 gclass = g_new0 (MonoGenericClass, 1);
8816 gclass->inst = g_new0 (MonoGenericInst, 1);
8817 gclass->inst->type_argc = kgclass->inst->type_argc;
8818 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8819 gclass->inst->is_reference = 1;
8821 for (i = 0; i < gclass->inst->type_argc; i++) {
8822 MonoType *t = kgclass->inst->type_argv [i];
8824 t = mono_class_inflate_generic_type (t, mono_generic_class_get_context (ogclass));
8826 if (!gclass->inst->is_open)
8827 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8828 if (gclass->inst->is_reference)
8829 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8831 gclass->inst->type_argv [i] = t;
8834 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8836 gclass->container_class = kgclass->container_class;
8839 geninst = g_new0 (MonoType, 1);
8840 geninst->type = MONO_TYPE_GENERICINST;
8842 cached = mono_metadata_lookup_generic_class (gclass);
8845 mono_loader_unlock ();
8846 geninst->data.generic_class = cached;
8850 geninst->data.generic_class = gclass;
8852 mono_loader_unlock ();
8857 static inline MonoType*
8858 dup_type (const MonoType *original)
8860 MonoType *r = g_new0 (MonoType, 1);
8862 r->attrs = original->attrs;
8863 r->byref = original->byref;
8864 if (original->type == MONO_TYPE_PTR)
8865 r->data.type = dup_type (original->data.type);
8866 else if (original->type == MONO_TYPE_ARRAY)
8867 r->data.array = mono_dup_array_type (original->data.array);
8868 else if (original->type == MONO_TYPE_FNPTR)
8869 r->data.method = mono_metadata_signature_deep_dup (original->data.method);
8870 mono_stats.generics_metadata_size += sizeof (MonoType);
8874 MonoReflectionMethod*
8875 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8877 MonoMethod *method, *inflated;
8878 MonoReflectionMethodBuilder *mb = NULL;
8879 MonoGenericContainer *container;
8880 MonoGenericMethod *gmethod;
8881 MonoGenericContext *context;
8882 MonoGenericInst *ginst;
8885 MONO_ARCH_SAVE_REGS;
8886 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8887 MonoReflectionTypeBuilder *tb;
8890 mb = (MonoReflectionMethodBuilder *) rmethod;
8891 tb = (MonoReflectionTypeBuilder *) mb->type;
8892 klass = mono_class_from_mono_type (tb->type.type);
8894 method = methodbuilder_to_mono_method (klass, mb);
8896 method = rmethod->method;
8899 method = mono_get_inflated_method (method);
8901 count = mono_method_signature (method)->generic_param_count;
8902 if (count != mono_array_length (types))
8905 container = method->generic_container;
8906 g_assert (container);
8908 if (!container->method_hash)
8909 container->method_hash = g_hash_table_new (
8910 (GHashFunc) mono_metadata_generic_method_hash,
8911 (GCompareFunc) mono_metadata_generic_method_equal);
8913 ginst = g_new0 (MonoGenericInst,1 );
8914 ginst->type_argc = count;
8915 ginst->type_argv = g_new0 (MonoType *, count);
8916 ginst->is_reference = 1;
8917 for (i = 0; i < count; i++) {
8918 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8919 ginst->type_argv [i] = dup_type (garg->type);
8921 if (!ginst->is_open)
8922 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8923 if (ginst->is_reference)
8924 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8926 ginst = mono_metadata_lookup_generic_inst (ginst);
8928 gmethod = g_new0 (MonoGenericMethod, 1);
8929 if (method->klass->generic_class)
8930 gmethod->class_inst = method->klass->generic_class->inst;
8931 gmethod->container = container;
8932 gmethod->inst = ginst;
8934 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8938 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8941 MOVING_GC_REGISTER (&gmethod->reflection_info);
8942 gmethod->reflection_info = rmethod;
8944 context = g_new0 (MonoGenericContext, 1);
8945 context->class_inst = gmethod->class_inst;
8946 context->gmethod = gmethod;
8948 if (method->is_inflated)
8949 method = ((MonoMethodInflated *) method)->declaring;
8951 inflated = mono_class_inflate_generic_method (method, context);
8952 g_hash_table_insert (container->method_hash, gmethod, inflated);
8954 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8958 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8960 MonoGenericMethod *gmethod = NULL;
8961 MonoGenericContext *context;
8964 klass = mono_class_from_mono_type (type->type.type);
8965 g_assert (klass->generic_class);
8966 context = mono_class_get_context (klass);
8968 if (method->generic_container) {
8969 g_assert (method->klass == klass->generic_class->container_class);
8971 gmethod = g_new0 (MonoGenericMethod, 1);
8972 gmethod->class_inst = klass->generic_class->inst;
8973 gmethod->container = method->generic_container;
8974 MOVING_GC_REGISTER (&gmethod->reflection_info);
8975 gmethod->reflection_info = obj;
8976 gmethod->inst = method->generic_container->context.gmethod->inst;
8978 context = g_new0 (MonoGenericContext, 1);
8979 context->class_inst = klass->generic_class->inst;
8980 context->gmethod = gmethod;
8983 return mono_class_inflate_generic_method_full (method, klass, context);
8987 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8992 gklass = mono_class_from_mono_type (type->generic_type->type);
8994 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8995 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
8996 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8997 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
8998 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8999 method = ((MonoReflectionMethod *) obj)->method;
9001 method = NULL; /* prevent compiler warning */
9002 g_assert_not_reached ();
9005 return inflate_mono_method (type, method, obj);
9009 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9010 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9013 MonoGenericClass *gclass;
9014 MonoDynamicGenericClass *dgclass;
9015 MonoClass *klass, *gklass;
9018 MONO_ARCH_SAVE_REGS;
9020 klass = mono_class_from_mono_type (type->type.type);
9021 gclass = type->type.type->data.generic_class;
9023 g_assert (gclass->is_dynamic);
9024 dgclass = (MonoDynamicGenericClass *) gclass;
9026 if (dgclass->initialized)
9029 gklass = gclass->container_class;
9030 mono_class_init (gklass);
9032 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9033 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9034 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9035 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9036 dgclass->count_events = events ? mono_array_length (events) : 0;
9038 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9039 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9040 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9041 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9042 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9044 for (i = 0; i < dgclass->count_methods; i++) {
9045 MonoObject *obj = mono_array_get (methods, gpointer, i);
9047 dgclass->methods [i] = inflate_method (type, obj);
9050 for (i = 0; i < dgclass->count_ctors; i++) {
9051 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9053 dgclass->ctors [i] = inflate_method (type, obj);
9056 for (i = 0; i < dgclass->count_fields; i++) {
9057 MonoObject *obj = mono_array_get (fields, gpointer, i);
9058 MonoClassField *field;
9059 MonoInflatedField *ifield;
9061 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9062 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9063 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9064 field = ((MonoReflectionField *) obj)->field;
9066 field = NULL; /* prevent compiler warning */
9067 g_assert_not_reached ();
9070 ifield = g_new0 (MonoInflatedField, 1);
9071 ifield->generic_type = field->type;
9072 MOVING_GC_REGISTER (&ifield->reflection_info);
9073 ifield->reflection_info = obj;
9075 dgclass->fields [i] = *field;
9076 dgclass->fields [i].parent = klass;
9077 dgclass->fields [i].generic_info = ifield;
9078 dgclass->fields [i].type = mono_class_inflate_generic_type (
9079 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9082 for (i = 0; i < dgclass->count_properties; i++) {
9083 MonoObject *obj = mono_array_get (properties, gpointer, i);
9084 MonoProperty *property = &dgclass->properties [i];
9086 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9087 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9089 property->parent = klass;
9090 property->attrs = pb->attrs;
9091 property->name = mono_string_to_utf8 (pb->name);
9093 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9095 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9096 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9097 *property = *((MonoReflectionProperty *) obj)->property;
9100 property->get = inflate_mono_method (type, property->get, NULL);
9102 property->set = inflate_mono_method (type, property->set, NULL);
9104 g_assert_not_reached ();
9107 for (i = 0; i < dgclass->count_events; i++) {
9108 MonoObject *obj = mono_array_get (events, gpointer, i);
9109 MonoEvent *event = &dgclass->events [i];
9111 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9112 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9114 event->parent = klass;
9115 event->attrs = eb->attrs;
9116 event->name = mono_string_to_utf8 (eb->name);
9118 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9119 if (eb->remove_method)
9120 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9121 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9122 *event = *((MonoReflectionEvent *) obj)->event;
9125 event->add = inflate_mono_method (type, event->add, NULL);
9127 event->remove = inflate_mono_method (type, event->remove, NULL);
9129 g_assert_not_reached ();
9132 dgclass->initialized = TRUE;
9136 ensure_runtime_vtable (MonoClass *klass)
9138 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9141 if (!tb || klass->wastypebuilder)
9144 ensure_runtime_vtable (klass->parent);
9146 num = tb->ctors? mono_array_length (tb->ctors): 0;
9147 num += tb->num_methods;
9148 klass->method.count = num;
9149 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9150 num = tb->ctors? mono_array_length (tb->ctors): 0;
9151 for (i = 0; i < num; ++i)
9152 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9153 num = tb->num_methods;
9155 for (i = 0; i < num; ++i)
9156 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9158 if (tb->interfaces) {
9159 klass->interface_count = mono_array_length (tb->interfaces);
9160 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9161 for (i = 0; i < klass->interface_count; ++i) {
9162 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9163 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9167 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9168 for (i = 0; i < klass->method.count; ++i)
9169 klass->methods [i]->slot = i;
9171 mono_class_setup_interface_offsets (klass);
9175 * The generic vtable is needed even if image->run is not set since some
9176 * runtime code like ves_icall_Type_GetMethodsByName depends on
9177 * method->slot being defined.
9181 * tb->methods could not be freed since it is used for determining
9182 * overrides during dynamic vtable construction.
9187 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9189 MonoReflectionTypeBuilder *tb;
9195 g_assert (klass->image->dynamic);
9197 if (!klass->reflection_info)
9200 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9202 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9206 for (i = 0; i < tb->num_methods; ++i) {
9207 MonoReflectionMethodBuilder *mb =
9208 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9209 if (mb->override_method)
9215 *overrides = g_new0 (MonoMethod*, onum * 2);
9218 for (i = 0; i < tb->num_methods; ++i) {
9219 MonoReflectionMethodBuilder *mb =
9220 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9221 if (mb->override_method) {
9222 (*overrides) [onum * 2] =
9223 mb->override_method->method;
9224 (*overrides) [onum * 2 + 1] =
9227 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9228 g_assert (mb->override_method->method);
9229 g_assert (mb->mhandle);
9236 *num_overrides = onum;
9240 typebuilder_setup_fields (MonoClass *klass)
9242 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9243 MonoReflectionFieldBuilder *fb;
9244 MonoClassField *field;
9249 klass->field.count = tb->num_fields;
9250 klass->field.first = 0;
9252 if (!klass->field.count)
9255 klass->fields = g_new0 (MonoClassField, klass->field.count);
9257 for (i = 0; i < klass->field.count; ++i) {
9258 fb = mono_array_get (tb->fields, gpointer, i);
9259 field = &klass->fields [i];
9260 field->name = mono_string_to_utf8 (fb->name);
9262 /* FIXME: handle type modifiers */
9263 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9264 field->type->attrs = fb->attrs;
9266 field->type = fb->type->type;
9268 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9269 field->data = mono_array_addr (fb->rva_data, char, 0);
9270 if (fb->offset != -1)
9271 field->offset = fb->offset;
9272 field->parent = klass;
9274 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9276 if (fb->def_value) {
9277 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9278 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9279 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9280 /* Copy the data from the blob since it might get realloc-ed */
9281 p = assembly->blob.data + idx;
9282 len = mono_metadata_decode_blob_size (p, &p2);
9284 field->data = g_malloc (len);
9285 memcpy ((gpointer)field->data, p, len);
9288 mono_class_layout_fields (klass);
9292 typebuilder_setup_properties (MonoClass *klass)
9294 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9295 MonoReflectionPropertyBuilder *pb;
9298 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9299 klass->property.first = 0;
9301 klass->properties = g_new0 (MonoProperty, klass->property.count);
9302 for (i = 0; i < klass->property.count; ++i) {
9303 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9304 klass->properties [i].parent = klass;
9305 klass->properties [i].attrs = pb->attrs;
9306 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9308 klass->properties [i].get = pb->get_method->mhandle;
9310 klass->properties [i].set = pb->set_method->mhandle;
9312 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9316 MonoReflectionEvent *
9317 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9319 MonoEvent *event = g_new0 (MonoEvent, 1);
9323 klass = my_mono_class_from_mono_type (tb->type.type);
9325 event->parent = klass;
9326 event->attrs = eb->attrs;
9327 event->name = mono_string_to_utf8 (eb->name);
9329 event->add = eb->add_method->mhandle;
9330 if (eb->remove_method)
9331 event->remove = eb->remove_method->mhandle;
9332 if (eb->raise_method)
9333 event->raise = eb->raise_method->mhandle;
9335 if (eb->other_methods) {
9336 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9337 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9338 MonoReflectionMethodBuilder *mb =
9339 mono_array_get (eb->other_methods,
9340 MonoReflectionMethodBuilder*, j);
9341 event->other [j] = mb->mhandle;
9345 return mono_event_get_object (mono_object_domain (tb), klass, event);
9349 typebuilder_setup_events (MonoClass *klass)
9351 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9352 MonoReflectionEventBuilder *eb;
9355 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9356 klass->event.first = 0;
9358 klass->events = g_new0 (MonoEvent, klass->event.count);
9359 for (i = 0; i < klass->event.count; ++i) {
9360 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9361 klass->events [i].parent = klass;
9362 klass->events [i].attrs = eb->attrs;
9363 klass->events [i].name = mono_string_to_utf8 (eb->name);
9365 klass->events [i].add = eb->add_method->mhandle;
9366 if (eb->remove_method)
9367 klass->events [i].remove = eb->remove_method->mhandle;
9368 if (eb->raise_method)
9369 klass->events [i].raise = eb->raise_method->mhandle;
9371 if (eb->other_methods) {
9372 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9373 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9374 MonoReflectionMethodBuilder *mb =
9375 mono_array_get (eb->other_methods,
9376 MonoReflectionMethodBuilder*, j);
9377 klass->events [i].other [j] = mb->mhandle;
9384 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9388 MonoReflectionType* res;
9391 MONO_ARCH_SAVE_REGS;
9393 domain = mono_object_domain (tb);
9394 klass = my_mono_class_from_mono_type (tb->type.type);
9396 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9399 * we need to lock the domain because the lock will be taken inside
9400 * So, we need to keep the locking order correct.
9402 mono_domain_lock (domain);
9403 mono_loader_lock ();
9404 if (klass->wastypebuilder) {
9405 mono_loader_unlock ();
9406 mono_domain_unlock (domain);
9407 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9410 * Fields to set in klass:
9411 * the various flags: delegate/unicode/contextbound etc.
9413 klass->flags = tb->attrs;
9414 klass->has_cctor = 1;
9415 klass->has_finalize = 1;
9418 if (!((MonoDynamicImage*)klass->image)->run) {
9419 if (klass->generic_container) {
9420 /* FIXME: The code below can't handle generic classes */
9421 klass->wastypebuilder = TRUE;
9422 mono_loader_unlock ();
9423 mono_domain_unlock (domain);
9424 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9429 /* enums are done right away */
9430 if (!klass->enumtype)
9431 ensure_runtime_vtable (klass);
9434 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9435 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9436 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9440 /* fields and object layout */
9441 if (klass->parent) {
9442 if (!klass->parent->size_inited)
9443 mono_class_init (klass->parent);
9444 klass->instance_size = klass->parent->instance_size;
9445 klass->sizes.class_size = 0;
9446 klass->min_align = klass->parent->min_align;
9447 /* if the type has no fields we won't call the field_setup
9448 * routine which sets up klass->has_references.
9450 klass->has_references |= klass->parent->has_references;
9452 klass->instance_size = sizeof (MonoObject);
9453 klass->min_align = 1;
9456 /* FIXME: handle packing_size and instance_size */
9457 typebuilder_setup_fields (klass);
9459 typebuilder_setup_properties (klass);
9461 typebuilder_setup_events (klass);
9463 klass->wastypebuilder = TRUE;
9464 mono_loader_unlock ();
9465 mono_domain_unlock (domain);
9467 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9468 g_assert (res != (MonoReflectionType*)tb);
9474 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9476 MonoGenericParam *param;
9479 MONO_ARCH_SAVE_REGS;
9481 param = g_new0 (MonoGenericParam, 1);
9483 if (gparam->mbuilder) {
9484 if (!gparam->mbuilder->generic_container)
9485 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9486 param->owner = gparam->mbuilder->generic_container;
9487 } else if (gparam->tbuilder) {
9488 g_assert (gparam->tbuilder->generic_container);
9489 param->owner = gparam->tbuilder->generic_container;
9492 param->method = NULL;
9493 param->name = mono_string_to_utf8 (gparam->name);
9494 param->num = gparam->index;
9496 image = &gparam->tbuilder->module->dynamic_image->image;
9497 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9499 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
9500 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9502 gparam->type.type = g_new0 (MonoType, 1);
9503 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9504 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9505 gparam->type.type->data.generic_param = param;
9509 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9511 MonoDynamicImage *assembly = sig->module->dynamic_image;
9512 guint32 na = mono_array_length (sig->arguments);
9513 guint32 buflen, i, size;
9517 MONO_ARCH_SAVE_REGS;
9519 p = buf = g_malloc (size = 50 + na * 50);
9521 mono_metadata_encode_value (0x07, p, &p);
9522 mono_metadata_encode_value (na, p, &p);
9523 for (i = 0; i < na; ++i) {
9524 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9525 encode_reflection_type (assembly, type, p, &p);
9529 g_assert (buflen < size);
9530 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9531 p = mono_array_addr (result, char, 0);
9532 memcpy (p, buf, buflen);
9539 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9541 MonoDynamicImage *assembly = sig->module->dynamic_image;
9542 guint32 na = mono_array_length (sig->arguments);
9543 guint32 buflen, i, size;
9547 MONO_ARCH_SAVE_REGS;
9549 p = buf = g_malloc (size = 10 + na * 10);
9551 mono_metadata_encode_value (0x06, p, &p);
9552 for (i = 0; i < na; ++i) {
9553 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9554 encode_reflection_type (assembly, type, p, &p);
9558 g_assert (buflen < size);
9559 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9560 p = mono_array_addr (result, char, 0);
9561 memcpy (p, buf, buflen);
9568 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9570 ReflectionMethodBuilder rmb;
9571 MonoMethodSignature *sig;
9574 sig = dynamic_method_to_signature (mb);
9576 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9579 * Resolve references.
9582 * Every second entry in the refs array is reserved for storing handle_class,
9583 * which is needed by the ldtoken implementation in the JIT.
9585 rmb.nrefs = mb->nrefs;
9586 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9587 for (i = 0; i < mb->nrefs; i += 2) {
9588 MonoClass *handle_class;
9589 gpointer ref = resolve_object (mb->module->image,
9590 mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9593 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9596 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9597 rmb.refs [i + 1] = handle_class;
9601 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9605 /* ilgen is no longer needed */
9610 * mono_reflection_lookup_dynamic_token:
9612 * Finish the Builder object pointed to by TOKEN and return the corresponding
9613 * runtime structure. HANDLE_CLASS is set to the class required by
9617 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9619 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9622 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9625 return resolve_object (image, obj, handle_class);
9629 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9631 gpointer result = NULL;
9633 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9634 result = mono_string_intern ((MonoString*)obj);
9635 *handle_class = NULL;
9637 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9638 MonoReflectionType *tb = (MonoReflectionType*)obj;
9639 result = mono_class_from_mono_type (tb->type);
9640 *handle_class = mono_defaults.typehandle_class;
9642 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9643 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9644 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9645 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9646 result = ((MonoReflectionMethod*)obj)->method;
9647 *handle_class = mono_defaults.methodhandle_class;
9649 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9650 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9651 result = mb->mhandle;
9653 /* Type is not yet created */
9654 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9656 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9659 * Hopefully this has been filled in by calling CreateType() on the
9663 * TODO: This won't work if the application finishes another
9664 * TypeBuilder instance instead of this one.
9666 result = mb->mhandle;
9668 *handle_class = mono_defaults.methodhandle_class;
9669 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9670 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9672 result = cb->mhandle;
9674 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9676 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9677 result = cb->mhandle;
9679 *handle_class = mono_defaults.methodhandle_class;
9680 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9681 result = ((MonoReflectionField*)obj)->field;
9682 *handle_class = mono_defaults.fieldhandle_class;
9684 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9685 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9686 result = fb->handle;
9689 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9691 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9692 result = fb->handle;
9694 *handle_class = mono_defaults.fieldhandle_class;
9695 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9696 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9699 klass = tb->type.type->data.klass;
9700 if (klass->wastypebuilder) {
9701 /* Already created */
9705 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9706 result = tb->type.type->data.klass;
9709 *handle_class = mono_defaults.typehandle_class;
9710 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9711 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9712 MonoMethodSignature *sig;
9715 if (helper->arguments)
9716 nargs = mono_array_length (helper->arguments);
9720 sig = mono_metadata_signature_alloc (image, nargs);
9721 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9722 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9724 if (helper->call_conv == 0) /* unmanaged */
9725 sig->call_convention = helper->unmanaged_call_conv - 1;
9727 if (helper->call_conv & 0x02)
9728 sig->call_convention = MONO_CALL_VARARG;
9730 sig->call_convention = MONO_CALL_DEFAULT;
9732 sig->param_count = nargs;
9733 /* TODO: Copy type ? */
9734 sig->ret = helper->return_type->type;
9735 for (i = 0; i < nargs; ++i) {
9736 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9737 sig->params [i] = rt->type;
9741 *handle_class = NULL;
9742 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9743 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9744 /* Already created by the managed code */
9745 g_assert (method->mhandle);
9746 result = method->mhandle;
9747 *handle_class = mono_defaults.methodhandle_class;
9749 g_print (obj->vtable->klass->name);
9750 g_assert_not_reached ();
9756 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9757 const static guint32 declsec_flags_map[] = {
9758 0x00000000, /* empty */
9759 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9760 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9761 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9762 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9763 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9764 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9765 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9766 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9767 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9768 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9769 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9770 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9771 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9772 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9773 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9774 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9775 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9776 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9780 * Returns flags that includes all available security action associated to the handle.
9781 * @token: metadata token (either for a class or a method)
9782 * @image: image where resides the metadata.
9785 mono_declsec_get_flags (MonoImage *image, guint32 token)
9787 guint32 index = mono_metadata_declsec_from_index (image, token);
9788 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9793 for (i = index; i < t->rows; i++) {
9794 guint32 cols [MONO_DECL_SECURITY_SIZE];
9796 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9797 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9800 action = cols [MONO_DECL_SECURITY_ACTION];
9801 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9802 result |= declsec_flags_map [action];
9804 g_assert_not_reached ();
9811 * Get the security actions (in the form of flags) associated with the specified method.
9813 * @method: The method for which we want the declarative security flags.
9814 * Return the declarative security flags for the method (only).
9816 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9817 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9820 mono_declsec_flags_from_method (MonoMethod *method)
9822 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9823 /* FIXME: No cache (for the moment) */
9824 guint32 idx = mono_method_get_index (method);
9825 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9826 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9827 return mono_declsec_get_flags (method->klass->image, idx);
9833 * Get the security actions (in the form of flags) associated with the specified class.
9835 * @klass: The class for which we want the declarative security flags.
9836 * Return the declarative security flags for the class.
9838 * Note: We cache the flags inside the MonoClass structure as this will get
9839 * called very often (at least for each method).
9842 mono_declsec_flags_from_class (MonoClass *klass)
9844 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9845 if (!klass->declsec_flags) {
9846 guint32 idx = mono_metadata_token_index (klass->type_token);
9847 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9848 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9849 /* we cache the flags on classes */
9850 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9852 return klass->declsec_flags;
9858 * Get the security actions (in the form of flags) associated with the specified assembly.
9860 * @assembly: The assembly for which we want the declarative security flags.
9861 * Return the declarative security flags for the assembly.
9864 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9866 guint32 idx = 1; /* there is only one assembly */
9867 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9868 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9869 return mono_declsec_get_flags (assembly->image, idx);
9874 * Fill actions for the specific index (which may either be an encoded class token or
9875 * an encoded method token) from the metadata image.
9876 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9879 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9880 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9882 MonoBoolean result = FALSE;
9884 guint32 cols [MONO_DECL_SECURITY_SIZE];
9885 int index = mono_metadata_declsec_from_index (image, token);
9888 t = &image->tables [MONO_TABLE_DECLSECURITY];
9889 for (i = index; i < t->rows; i++) {
9890 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9892 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9895 /* if present only replace (class) permissions with method permissions */
9896 /* if empty accept either class or method permissions */
9897 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9898 if (!actions->demand.blob) {
9899 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9900 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9901 actions->demand.blob = (char*) (blob + 2);
9902 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9905 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9906 if (!actions->noncasdemand.blob) {
9907 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9908 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9909 actions->noncasdemand.blob = (char*) (blob + 2);
9910 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9913 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9914 if (!actions->demandchoice.blob) {
9915 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9916 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9917 actions->demandchoice.blob = (char*) (blob + 2);
9918 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9928 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9929 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9931 guint32 idx = mono_metadata_token_index (klass->type_token);
9932 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9933 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9934 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9938 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9939 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9941 guint32 idx = mono_method_get_index (method);
9942 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9943 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9944 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9948 * Collect all actions (that requires to generate code in mini) assigned for
9949 * the specified method.
9950 * Note: Don't use the content of actions if the function return FALSE.
9953 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9955 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9956 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9957 MonoBoolean result = FALSE;
9960 /* quick exit if no declarative security is present in the metadata */
9961 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9964 /* we want the original as the wrapper is "free" of the security informations */
9965 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
9966 method = mono_marshal_method_from_wrapper (method);
9971 /* First we look for method-level attributes */
9972 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9973 mono_class_init (method->klass);
9974 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9976 result = mono_declsec_get_method_demands_params (method, demands,
9977 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9980 /* Here we use (or create) the class declarative cache to look for demands */
9981 flags = mono_declsec_flags_from_class (method->klass);
9984 mono_class_init (method->klass);
9985 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9987 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9988 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9991 /* The boolean return value is used as a shortcut in case nothing needs to
9992 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9998 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10000 * Note: Don't use the content of actions if the function return FALSE.
10003 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10005 MonoBoolean result = FALSE;
10008 /* quick exit if no declarative security is present in the metadata */
10009 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10012 /* we want the original as the wrapper is "free" of the security informations */
10013 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10014 method = mono_marshal_method_from_wrapper (method);
10019 /* results are independant - zeroize both */
10020 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10021 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10023 /* First we look for method-level attributes */
10024 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10025 mono_class_init (method->klass);
10027 result = mono_declsec_get_method_demands_params (method, cmethod,
10028 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10031 /* Here we use (or create) the class declarative cache to look for demands */
10032 flags = mono_declsec_flags_from_class (method->klass);
10033 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10034 mono_class_init (method->klass);
10036 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10037 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10044 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10046 * @klass The inherited class - this is the class that provides the security check (attributes)
10048 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10050 * Note: Don't use the content of actions if the function return FALSE.
10053 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10055 MonoBoolean result = FALSE;
10058 /* quick exit if no declarative security is present in the metadata */
10059 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10062 /* Here we use (or create) the class declarative cache to look for demands */
10063 flags = mono_declsec_flags_from_class (klass);
10064 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10065 mono_class_init (klass);
10066 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10068 result |= mono_declsec_get_class_demands_params (klass, demands,
10069 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10076 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10078 * Note: Don't use the content of actions if the function return FALSE.
10081 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10083 /* quick exit if no declarative security is present in the metadata */
10084 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10087 /* we want the original as the wrapper is "free" of the security informations */
10088 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10089 method = mono_marshal_method_from_wrapper (method);
10094 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10095 mono_class_init (method->klass);
10096 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10098 return mono_declsec_get_method_demands_params (method, demands,
10099 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10106 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10108 guint32 cols [MONO_DECL_SECURITY_SIZE];
10112 int index = mono_metadata_declsec_from_index (image, token);
10116 t = &image->tables [MONO_TABLE_DECLSECURITY];
10117 for (i = index; i < t->rows; i++) {
10118 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10120 /* shortcut - index are ordered */
10121 if (token != cols [MONO_DECL_SECURITY_PARENT])
10124 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10125 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10126 entry->blob = (char*) (metadata + 2);
10127 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10136 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10138 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10139 guint32 idx = mono_method_get_index (method);
10140 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10141 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10142 return get_declsec_action (method->klass->image, idx, action, entry);
10148 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10151 guint32 flags = mono_declsec_flags_from_class (klass);
10152 if (declsec_flags_map [action] & flags) {
10153 guint32 idx = mono_metadata_token_index (klass->type_token);
10154 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10155 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10156 return get_declsec_action (klass->image, idx, action, entry);
10162 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10164 guint32 idx = 1; /* there is only one assembly */
10165 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10166 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10168 return get_declsec_action (assembly->image, idx, action, entry);
10172 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10174 MonoObject *res, *exc;
10176 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10177 static MonoMethod *method = NULL;
10179 if (!System_Reflection_Emit_TypeBuilder) {
10180 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10181 g_assert (System_Reflection_Emit_TypeBuilder);
10183 if (method == NULL) {
10184 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10189 * The result of mono_type_get_object () might be a System.MonoType but we
10190 * need a TypeBuilder so use klass->reflection_info.
10192 g_assert (klass->reflection_info);
10193 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10195 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10197 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10201 return *(MonoBoolean*)mono_object_unbox (res);