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);
3745 offset = mono_array_length (rsrc->data);
3746 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3747 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3748 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3749 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3753 * The entry should be emitted into the MANIFESTRESOURCE table of
3754 * the main module, but that needs to reference the FILE table
3755 * which isn't emitted yet.
3762 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3766 set_version_from_string (MonoString *version, guint32 *values)
3768 gchar *ver, *p, *str;
3771 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3772 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3773 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3774 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3777 ver = str = mono_string_to_utf8 (version);
3778 for (i = 0; i < 4; ++i) {
3779 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3785 /* handle Revision and Build */
3795 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3799 char *b = blob_size;
3804 len = mono_array_length (pkey);
3805 mono_metadata_encode_value (len, b, &b);
3806 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3807 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3809 /* Special case: check for ECMA key (16 bytes) */
3810 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, guint8, 0), len)) {
3811 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3812 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3813 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3814 /* minimum key size (in 2.0) is 384 bits */
3815 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3817 /* FIXME - verifier */
3818 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3819 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3821 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3827 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3829 MonoDynamicTable *table;
3830 MonoDynamicImage *assembly;
3831 MonoReflectionAssemblyBuilder *assemblyb;
3835 guint32 module_index;
3837 assemblyb = moduleb->assemblyb;
3838 assembly = moduleb->dynamic_image;
3839 domain = mono_object_domain (assemblyb);
3841 /* Emit ASSEMBLY table */
3842 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3843 alloc_table (table, 1);
3844 values = table->values + MONO_ASSEMBLY_SIZE;
3845 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3846 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3847 if (assemblyb->culture) {
3848 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3850 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3852 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3853 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3854 set_version_from_string (assemblyb->version, values);
3856 /* Emit FILE + EXPORTED_TYPE table */
3858 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3860 MonoReflectionModuleBuilder *file_module =
3861 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3862 if (file_module != moduleb) {
3863 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3865 if (file_module->types) {
3866 for (j = 0; j < file_module->num_types; ++j) {
3867 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3868 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3873 if (assemblyb->loaded_modules) {
3874 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3875 MonoReflectionModule *file_module =
3876 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3877 mono_image_fill_file_table (domain, file_module, assembly);
3879 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3882 if (assemblyb->type_forwarders)
3883 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3885 /* Emit MANIFESTRESOURCE table */
3887 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3889 MonoReflectionModuleBuilder *file_module =
3890 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3891 /* The table for the main module is emitted later */
3892 if (file_module != moduleb) {
3894 if (file_module->resources) {
3895 int len = mono_array_length (file_module->resources);
3896 for (j = 0; j < len; ++j) {
3897 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3898 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3906 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3907 * for the modulebuilder @moduleb.
3908 * At the end of the process, method and field tokens are fixed up and the
3909 * on-disk compressed metadata representation is created.
3912 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3914 MonoDynamicTable *table;
3915 MonoDynamicImage *assembly;
3916 MonoReflectionAssemblyBuilder *assemblyb;
3922 assemblyb = moduleb->assemblyb;
3923 assembly = moduleb->dynamic_image;
3924 domain = mono_object_domain (assemblyb);
3926 if (assembly->text_rva)
3929 assembly->text_rva = START_TEXT_RVA;
3931 if (moduleb->is_main) {
3932 mono_image_emit_manifest (moduleb);
3935 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3936 table->rows = 1; /* .<Module> */
3938 alloc_table (table, table->rows);
3940 * Set the first entry.
3942 values = table->values + table->columns;
3943 values [MONO_TYPEDEF_FLAGS] = 0;
3944 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3945 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3946 values [MONO_TYPEDEF_EXTENDS] = 0;
3947 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3948 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3951 * handle global methods
3952 * FIXME: test what to do when global methods are defined in multiple modules.
3954 if (moduleb->global_methods) {
3955 table = &assembly->tables [MONO_TABLE_METHOD];
3956 table->rows += mono_array_length (moduleb->global_methods);
3957 alloc_table (table, table->rows);
3958 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3959 mono_image_get_method_info (
3960 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3962 if (moduleb->global_fields) {
3963 table = &assembly->tables [MONO_TABLE_FIELD];
3964 table->rows += mono_array_length (moduleb->global_fields);
3965 alloc_table (table, table->rows);
3966 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3967 mono_image_get_field_info (
3968 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3971 table = &assembly->tables [MONO_TABLE_MODULE];
3972 alloc_table (table, 1);
3973 mono_image_fill_module_table (domain, moduleb, assembly);
3975 /* Collect all types into a list sorted by their table_idx */
3976 types = g_ptr_array_new ();
3979 for (i = 0; i < moduleb->num_types; ++i) {
3980 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3981 collect_types (types, type);
3984 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3985 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3986 table->rows += types->len;
3987 alloc_table (table, table->rows);
3990 * Emit type names + namespaces at one place inside the string heap,
3991 * so load_class_names () needs to touch fewer pages.
3993 for (i = 0; i < types->len; ++i) {
3994 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3995 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
3997 for (i = 0; i < types->len; ++i) {
3998 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3999 string_heap_insert_mstring (&assembly->sheap, tb->name);
4002 for (i = 0; i < types->len; ++i) {
4003 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4004 mono_image_get_type_info (domain, type, assembly);
4008 * table->rows is already set above and in mono_image_fill_module_table.
4010 /* add all the custom attributes at the end, once all the indexes are stable */
4011 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4013 /* CAS assembly permissions */
4014 if (assemblyb->permissions_minimum)
4015 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4016 if (assemblyb->permissions_optional)
4017 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4018 if (assemblyb->permissions_refused)
4019 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4021 module_add_cattrs (assembly, moduleb);
4024 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4026 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4027 * the final tokens and don't need another fixup pass. */
4029 if (moduleb->global_methods) {
4030 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4031 MonoReflectionMethodBuilder *mb = mono_array_get (
4032 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4033 mono_image_add_methodimpl (assembly, mb);
4037 for (i = 0; i < types->len; ++i) {
4038 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4039 if (type->methods) {
4040 for (j = 0; j < type->num_methods; ++j) {
4041 MonoReflectionMethodBuilder *mb = mono_array_get (
4042 type->methods, MonoReflectionMethodBuilder*, j);
4044 mono_image_add_methodimpl (assembly, mb);
4049 g_ptr_array_free (types, TRUE);
4051 fixup_cattrs (assembly);
4055 * mono_image_insert_string:
4056 * @module: module builder object
4059 * Insert @str into the user string stream of @module.
4062 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4064 MonoDynamicImage *assembly;
4069 MONO_ARCH_SAVE_REGS;
4071 if (!module->dynamic_image)
4072 mono_image_module_basic_init (module);
4074 assembly = module->dynamic_image;
4076 if (assembly->save) {
4077 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4078 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4079 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4081 char *swapped = g_malloc (2 * mono_string_length (str));
4082 const char *p = (const char*)mono_string_chars (str);
4084 swap_with_size (swapped, p, 2, mono_string_length (str));
4085 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4089 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4091 mono_image_add_stream_data (&assembly->us, "", 1);
4093 idx = assembly->us.index ++;
4096 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4098 return MONO_TOKEN_STRING | idx;
4102 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4107 klass = obj->vtable->klass;
4108 if (strcmp (klass->name, "MonoMethod") == 0) {
4109 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4110 MonoMethodSignature *sig, *old;
4111 guint32 sig_token, parent;
4114 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4116 nargs = mono_array_length (opt_param_types);
4117 old = mono_method_signature (method);
4118 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4120 sig->hasthis = old->hasthis;
4121 sig->explicit_this = old->explicit_this;
4122 sig->call_convention = old->call_convention;
4123 sig->generic_param_count = old->generic_param_count;
4124 sig->param_count = old->param_count + nargs;
4125 sig->sentinelpos = old->param_count;
4126 sig->ret = old->ret;
4128 for (i = 0; i < old->param_count; i++)
4129 sig->params [i] = old->params [i];
4131 for (i = 0; i < nargs; i++) {
4132 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4133 sig->params [old->param_count + i] = rt->type;
4136 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4137 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4138 parent >>= MONO_TYPEDEFORREF_BITS;
4140 parent <<= MONO_MEMBERREF_PARENT_BITS;
4141 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4143 sig_token = method_encode_signature (assembly, sig);
4144 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4145 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4146 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4147 ReflectionMethodBuilder rmb;
4148 guint32 parent, sig;
4150 reflection_methodbuilder_from_method_builder (&rmb, mb);
4151 rmb.opt_types = opt_param_types;
4153 sig = method_builder_encode_signature (assembly, &rmb);
4155 parent = mono_image_create_token (assembly, obj, TRUE);
4156 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4158 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4159 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4161 token = mono_image_get_varargs_method_token (
4162 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4164 g_error ("requested method token for %s\n", klass->name);
4171 * mono_image_create_token:
4172 * @assembly: a dynamic assembly
4175 * Get a token to insert in the IL code stream for the given MemberInfo.
4176 * @obj can be one of:
4177 * ConstructorBuilder
4187 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4192 klass = obj->vtable->klass;
4193 if (strcmp (klass->name, "MethodBuilder") == 0) {
4194 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4196 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4197 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4199 token = mono_image_get_methodbuilder_token (assembly, mb);
4200 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4201 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4202 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4204 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4205 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4207 token = mono_image_get_ctorbuilder_token (assembly, mb);
4208 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4209 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4210 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4211 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4212 if (tb->generic_params) {
4213 token = mono_image_get_generic_field_token (assembly, fb);
4215 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4217 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4218 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4219 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4220 } else if (strcmp (klass->name, "MonoType") == 0 ||
4221 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4222 MonoReflectionType *tb = (MonoReflectionType *)obj;
4223 token = mono_metadata_token_from_dor (
4224 mono_image_typedef_or_ref (assembly, tb->type));
4225 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4226 MonoReflectionType *tb = (MonoReflectionType *)obj;
4227 token = mono_metadata_token_from_dor (
4228 mono_image_typedef_or_ref (assembly, tb->type));
4229 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4230 strcmp (klass->name, "MonoMethod") == 0 ||
4231 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4232 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4233 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4234 if (m->method->is_inflated) {
4235 if (create_methodspec)
4236 token = mono_image_get_methodspec_token (assembly, m->method);
4238 token = mono_image_get_inflated_method_token (assembly, m->method);
4239 } else if ((m->method->klass->image == &assembly->image) &&
4240 !m->method->klass->generic_class) {
4241 static guint32 method_table_idx = 0xffffff;
4242 if (m->method->klass->wastypebuilder) {
4243 /* we use the same token as the one that was assigned
4244 * to the Methodbuilder.
4245 * FIXME: do the equivalent for Fields.
4247 token = m->method->token;
4250 * Each token should have a unique index, but the indexes are
4251 * assigned by managed code, so we don't know about them. An
4252 * easy solution is to count backwards...
4254 method_table_idx --;
4255 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4258 token = mono_image_get_methodref_token (assembly, m->method);
4260 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4261 } else if (strcmp (klass->name, "MonoField") == 0) {
4262 MonoReflectionField *f = (MonoReflectionField *)obj;
4263 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4264 static guint32 field_table_idx = 0xffffff;
4266 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4268 token = mono_image_get_fieldref_token (assembly, f);
4270 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4271 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4272 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4273 token = mono_image_get_array_token (assembly, m);
4274 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4275 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4276 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4278 g_error ("requested token for %s\n", klass->name);
4281 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4287 guint32 import_lookup_table;
4291 guint32 import_address_table_rva;
4299 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4301 static MonoDynamicImage*
4302 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4304 static const guchar entrycode [16] = {0xff, 0x25, 0};
4305 MonoDynamicImage *image;
4308 const char *version = mono_get_runtime_info ()->runtime_version;
4311 image = GC_MALLOC (sizeof (MonoDynamicImage));
4313 image = g_new0 (MonoDynamicImage, 1);
4316 /*g_print ("created image %p\n", image);*/
4317 /* keep in sync with image.c */
4318 image->image.name = assembly_name;
4319 image->image.assembly_name = image->image.name; /* they may be different */
4320 image->image.module_name = module_name;
4321 image->image.version = g_strdup (version);
4322 image->image.md_version_major = 1;
4323 image->image.md_version_minor = 1;
4324 image->image.dynamic = TRUE;
4326 image->image.references = g_new0 (MonoAssembly*, 1);
4327 image->image.references [0] = NULL;
4329 mono_image_init (&image->image);
4331 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4332 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4333 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4334 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4335 image->handleref = g_hash_table_new (NULL, NULL);
4336 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4337 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4338 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4339 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4340 image->gen_params = g_ptr_array_new ();
4342 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4343 string_heap_init (&image->sheap);
4344 mono_image_add_stream_data (&image->us, "", 1);
4345 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4346 /* import tables... */
4347 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4348 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4349 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4350 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4351 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4352 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4353 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4354 stream_data_align (&image->code);
4356 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4358 for (i=0; i < MONO_TABLE_NUM; ++i) {
4359 image->tables [i].next_idx = 1;
4360 image->tables [i].columns = table_sizes [i];
4363 image->image.assembly = (MonoAssembly*)assembly;
4364 image->run = assembly->run;
4365 image->save = assembly->save;
4366 image->pe_kind = 0x1; /* ILOnly */
4367 image->machine = 0x14c; /* I386 */
4373 * mono_image_basic_init:
4374 * @assembly: an assembly builder object
4376 * Create the MonoImage that represents the assembly builder and setup some
4377 * of the helper hash table and the basic metadata streams.
4380 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4382 MonoDynamicAssembly *assembly;
4383 MonoDynamicImage *image;
4384 MonoDomain *domain = mono_object_domain (assemblyb);
4386 MONO_ARCH_SAVE_REGS;
4388 if (assemblyb->dynamic_assembly)
4392 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4394 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4397 assembly->assembly.ref_count = 1;
4398 assembly->assembly.dynamic = TRUE;
4399 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4400 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4401 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4402 if (assemblyb->culture)
4403 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4405 assembly->assembly.aname.culture = g_strdup ("");
4407 if (assemblyb->version) {
4408 char *vstr = mono_string_to_utf8 (assemblyb->version);
4409 char **version = g_strsplit (vstr, ".", 4);
4410 char **parts = version;
4411 assembly->assembly.aname.major = atoi (*parts++);
4412 assembly->assembly.aname.minor = atoi (*parts++);
4413 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4414 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4416 g_strfreev (version);
4419 assembly->assembly.aname.major = 0;
4420 assembly->assembly.aname.minor = 0;
4421 assembly->assembly.aname.build = 0;
4422 assembly->assembly.aname.revision = 0;
4425 assembly->run = assemblyb->access != 2;
4426 assembly->save = assemblyb->access != 1;
4428 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4429 image->initial_image = TRUE;
4430 assembly->assembly.aname.name = image->image.name;
4431 assembly->assembly.image = &image->image;
4433 mono_domain_assemblies_lock (domain);
4434 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4435 mono_domain_assemblies_unlock (domain);
4437 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4438 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4442 calc_section_size (MonoDynamicImage *assembly)
4446 /* alignment constraints */
4447 assembly->code.index += 3;
4448 assembly->code.index &= ~3;
4449 assembly->meta_size += 3;
4450 assembly->meta_size &= ~3;
4451 assembly->resources.index += 3;
4452 assembly->resources.index &= ~3;
4454 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4455 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4458 if (assembly->win32_res) {
4459 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4461 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4462 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4466 assembly->sections [MONO_SECTION_RELOC].size = 12;
4467 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4477 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4481 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4483 ResTreeNode *t1 = (ResTreeNode*)a;
4484 ResTreeNode *t2 = (ResTreeNode*)b;
4486 return t1->id - t2->id;
4490 * resource_tree_create:
4492 * Organize the resources into a resource tree.
4494 static ResTreeNode *
4495 resource_tree_create (MonoArray *win32_resources)
4497 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4501 tree = g_new0 (ResTreeNode, 1);
4503 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4504 MonoReflectionWin32Resource *win32_res =
4505 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4509 /* FIXME: BUG: this stores managed references in unmanaged memory */
4510 lang_node = g_new0 (ResTreeNode, 1);
4511 lang_node->id = win32_res->lang_id;
4512 lang_node->win32_res = win32_res;
4514 /* Create type node if neccesary */
4516 for (l = tree->children; l; l = l->next)
4517 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4518 type_node = (ResTreeNode*)l->data;
4523 type_node = g_new0 (ResTreeNode, 1);
4524 type_node->id = win32_res->res_type;
4527 * The resource types have to be sorted otherwise
4528 * Windows Explorer can't display the version information.
4530 tree->children = g_slist_insert_sorted (tree->children,
4531 type_node, resource_tree_compare_by_id);
4534 /* Create res node if neccesary */
4536 for (l = type_node->children; l; l = l->next)
4537 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4538 res_node = (ResTreeNode*)l->data;
4543 res_node = g_new0 (ResTreeNode, 1);
4544 res_node->id = win32_res->res_id;
4545 type_node->children = g_slist_append (type_node->children, res_node);
4548 res_node->children = g_slist_append (res_node->children, lang_node);
4555 * resource_tree_encode:
4557 * Encode the resource tree into the format used in the PE file.
4560 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4563 MonoPEResourceDir dir;
4564 MonoPEResourceDirEntry dir_entry;
4565 MonoPEResourceDataEntry data_entry;
4569 * For the format of the resource directory, see the article
4570 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4574 memset (&dir, 0, sizeof (dir));
4575 memset (&dir_entry, 0, sizeof (dir_entry));
4576 memset (&data_entry, 0, sizeof (data_entry));
4578 g_assert (sizeof (dir) == 16);
4579 g_assert (sizeof (dir_entry) == 8);
4580 g_assert (sizeof (data_entry) == 16);
4582 node->offset = p - begin;
4584 /* IMAGE_RESOURCE_DIRECTORY */
4585 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4587 memcpy (p, &dir, sizeof (dir));
4590 /* Reserve space for entries */
4592 p += sizeof (dir_entry) * dir.res_id_entries;
4594 /* Write children */
4595 for (l = node->children; l; l = l->next) {
4596 ResTreeNode *child = (ResTreeNode*)l->data;
4598 if (child->win32_res) {
4600 child->offset = p - begin;
4602 /* IMAGE_RESOURCE_DATA_ENTRY */
4603 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4604 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4606 memcpy (p, &data_entry, sizeof (data_entry));
4607 p += sizeof (data_entry);
4609 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4610 p += data_entry.rde_size;
4612 resource_tree_encode (child, begin, p, &p);
4616 /* IMAGE_RESOURCE_ENTRY */
4617 for (l = node->children; l; l = l->next) {
4618 ResTreeNode *child = (ResTreeNode*)l->data;
4619 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4621 dir_entry.is_dir = child->win32_res ? 0 : 1;
4622 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4624 memcpy (entries, &dir_entry, sizeof (dir_entry));
4625 entries += sizeof (dir_entry);
4632 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4637 MonoReflectionWin32Resource *win32_res;
4640 if (!assemblyb->win32_resources)
4644 * Resources are stored in a three level tree inside the PE file.
4645 * - level one contains a node for each type of resource
4646 * - level two contains a node for each resource
4647 * - level three contains a node for each instance of a resource for a
4648 * specific language.
4651 tree = resource_tree_create (assemblyb->win32_resources);
4653 /* Estimate the size of the encoded tree */
4655 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4656 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4657 size += mono_array_length (win32_res->res_data);
4659 /* Directory structure */
4660 size += mono_array_length (assemblyb->win32_resources) * 256;
4661 p = buf = g_malloc (size);
4663 resource_tree_encode (tree, p, p, &p);
4665 g_assert (p - buf < size);
4667 assembly->win32_res = g_malloc (p - buf);
4668 assembly->win32_res_size = p - buf;
4669 memcpy (assembly->win32_res, buf, p - buf);
4675 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4677 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4680 p += sizeof (MonoPEResourceDir);
4681 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4682 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4683 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4684 if (dir_entry->is_dir) {
4685 fixup_resource_directory (res_section, child, rva);
4687 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4688 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4691 p += sizeof (MonoPEResourceDirEntry);
4696 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4699 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4700 g_error ("WriteFile returned %d\n", GetLastError ());
4704 * mono_image_create_pefile:
4705 * @mb: a module builder object
4707 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4708 * assembly->pefile where it can be easily retrieved later in chunks.
4711 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4712 MonoMSDOSHeader *msdos;
4713 MonoDotNetHeader *header;
4714 MonoSectionTable *section;
4715 MonoCLIHeader *cli_header;
4716 guint32 size, image_size, virtual_base, text_offset;
4717 guint32 header_start, section_start, file_offset, virtual_offset;
4718 MonoDynamicImage *assembly;
4719 MonoReflectionAssemblyBuilder *assemblyb;
4720 MonoDynamicStream pefile_stream = {0};
4721 MonoDynamicStream *pefile = &pefile_stream;
4723 guint32 *rva, value;
4725 static const unsigned char msheader[] = {
4726 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4727 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4730 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4731 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4732 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4733 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4736 assemblyb = mb->assemblyb;
4738 mono_image_basic_init (assemblyb);
4739 assembly = mb->dynamic_image;
4741 assembly->pe_kind = assemblyb->pe_kind;
4742 assembly->machine = assemblyb->machine;
4743 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4744 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4746 mono_image_build_metadata (mb);
4748 if (mb->is_main && assemblyb->resources) {
4749 int len = mono_array_length (assemblyb->resources);
4750 for (i = 0; i < len; ++i)
4751 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4754 if (mb->resources) {
4755 int len = mono_array_length (mb->resources);
4756 for (i = 0; i < len; ++i)
4757 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4760 build_compressed_metadata (assembly);
4763 assembly_add_win32_resources (assembly, assemblyb);
4765 nsections = calc_section_size (assembly);
4767 /* The DOS header and stub */
4768 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4769 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4771 /* the dotnet header */
4772 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4774 /* the section tables */
4775 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4777 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4778 virtual_offset = VIRT_ALIGN;
4781 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4782 if (!assembly->sections [i].size)
4785 file_offset += FILE_ALIGN - 1;
4786 file_offset &= ~(FILE_ALIGN - 1);
4787 virtual_offset += VIRT_ALIGN - 1;
4788 virtual_offset &= ~(VIRT_ALIGN - 1);
4790 assembly->sections [i].offset = file_offset;
4791 assembly->sections [i].rva = virtual_offset;
4793 file_offset += assembly->sections [i].size;
4794 virtual_offset += assembly->sections [i].size;
4795 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4798 file_offset += FILE_ALIGN - 1;
4799 file_offset &= ~(FILE_ALIGN - 1);
4801 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4803 /* back-patch info */
4804 msdos = (MonoMSDOSHeader*)pefile->data;
4805 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4807 header = (MonoDotNetHeader*)(pefile->data + header_start);
4808 header->pesig [0] = 'P';
4809 header->pesig [1] = 'E';
4811 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4812 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4813 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4814 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4815 if (assemblyb->pekind == 1) {
4817 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4820 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4823 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4825 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4826 header->pe.pe_major = 6;
4827 header->pe.pe_minor = 0;
4828 size = assembly->sections [MONO_SECTION_TEXT].size;
4829 size += FILE_ALIGN - 1;
4830 size &= ~(FILE_ALIGN - 1);
4831 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4832 size = assembly->sections [MONO_SECTION_RSRC].size;
4833 size += FILE_ALIGN - 1;
4834 size &= ~(FILE_ALIGN - 1);
4835 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4836 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4837 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4838 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4839 /* pe_rva_entry_point always at the beginning of the text section */
4840 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4842 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4843 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4844 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4845 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4846 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4847 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4848 size = section_start;
4849 size += FILE_ALIGN - 1;
4850 size &= ~(FILE_ALIGN - 1);
4851 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4853 size += VIRT_ALIGN - 1;
4854 size &= ~(VIRT_ALIGN - 1);
4855 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4858 // Translate the PEFileKind value to the value expected by the Windows loader
4864 // PEFileKinds.Dll == 1
4865 // PEFileKinds.ConsoleApplication == 2
4866 // PEFileKinds.WindowApplication == 3
4869 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4870 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4872 if (assemblyb->pekind == 3)
4877 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4879 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4880 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4881 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4882 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4883 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4884 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4886 /* fill data directory entries */
4888 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4889 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4891 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4892 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4894 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4895 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4896 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4897 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4898 /* patch entrypoint name */
4899 if (assemblyb->pekind == 1)
4900 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4902 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4903 /* patch imported function RVA name */
4904 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4905 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4907 /* the import table */
4908 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4909 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4910 /* patch imported dll RVA name and other entries in the dir */
4911 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4912 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4913 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4914 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4915 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4916 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4918 p = (assembly->code.data + assembly->ilt_offset);
4919 value = (assembly->text_rva + assembly->imp_names_offset);
4920 *p++ = (value) & 0xff;
4921 *p++ = (value >> 8) & (0xff);
4922 *p++ = (value >> 16) & (0xff);
4923 *p++ = (value >> 24) & (0xff);
4925 /* the CLI header info */
4926 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4927 cli_header->ch_size = GUINT32_FROM_LE (72);
4928 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4929 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4930 if (assemblyb->entry_point) {
4931 guint32 table_idx = 0;
4932 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4933 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4934 table_idx = methodb->table_idx;
4936 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4938 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4940 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4942 /* The embedded managed resources */
4943 text_offset = assembly->text_rva + assembly->code.index;
4944 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4945 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4946 text_offset += assembly->resources.index;
4947 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4948 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4949 text_offset += assembly->meta_size;
4950 if (assembly->strong_name_size) {
4951 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4952 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4953 text_offset += assembly->strong_name_size;
4956 /* write the section tables and section content */
4957 section = (MonoSectionTable*)(pefile->data + section_start);
4958 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4959 static const char section_names [][7] = {
4960 ".text", ".rsrc", ".reloc"
4962 if (!assembly->sections [i].size)
4964 strcpy (section->st_name, section_names [i]);
4965 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4966 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4967 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4968 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4969 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4970 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4971 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4975 checked_write_file (file, pefile->data, pefile->index);
4977 mono_dynamic_stream_reset (pefile);
4979 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4980 if (!assembly->sections [i].size)
4983 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4984 g_error ("SetFilePointer returned %d\n", GetLastError ());
4987 case MONO_SECTION_TEXT:
4988 /* patch entry point */
4989 p = (assembly->code.data + 2);
4990 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4991 *p++ = (value) & 0xff;
4992 *p++ = (value >> 8) & 0xff;
4993 *p++ = (value >> 16) & 0xff;
4994 *p++ = (value >> 24) & 0xff;
4996 checked_write_file (file, assembly->code.data, assembly->code.index);
4997 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4998 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4999 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5002 g_free (assembly->image.raw_metadata);
5004 case MONO_SECTION_RELOC: {
5008 guint16 type_and_offset;
5012 g_assert (sizeof (reloc) == 12);
5014 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5015 reloc.block_size = GUINT32_FROM_LE (12);
5018 * the entrypoint is always at the start of the text section
5019 * 3 is IMAGE_REL_BASED_HIGHLOW
5020 * 2 is patch_size_rva - text_rva
5022 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5025 checked_write_file (file, &reloc, sizeof (reloc));
5029 case MONO_SECTION_RSRC:
5030 if (assembly->win32_res) {
5032 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5033 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5034 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5038 g_assert_not_reached ();
5042 /* check that the file is properly padded */
5043 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5044 g_error ("SetFilePointer returned %d\n", GetLastError ());
5045 if (! SetEndOfFile (file))
5046 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5048 mono_dynamic_stream_reset (&assembly->code);
5049 mono_dynamic_stream_reset (&assembly->us);
5050 mono_dynamic_stream_reset (&assembly->blob);
5051 mono_dynamic_stream_reset (&assembly->guid);
5052 mono_dynamic_stream_reset (&assembly->sheap);
5054 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5055 g_hash_table_destroy (assembly->blob_cache);
5056 assembly->blob_cache = NULL;
5059 MonoReflectionModule *
5060 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5064 MonoImageOpenStatus status;
5065 MonoDynamicAssembly *assembly;
5066 guint32 module_count;
5067 MonoImage **new_modules;
5069 name = mono_string_to_utf8 (fileName);
5071 image = mono_image_open (name, &status);
5074 if (status == MONO_IMAGE_ERROR_ERRNO)
5075 exc = mono_get_exception_file_not_found (fileName);
5077 exc = mono_get_exception_bad_image_format (name);
5079 mono_raise_exception (exc);
5084 assembly = ab->dynamic_assembly;
5085 image->assembly = (MonoAssembly*)assembly;
5087 module_count = image->assembly->image->module_count;
5088 new_modules = g_new0 (MonoImage *, module_count + 1);
5090 if (image->assembly->image->modules)
5091 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5092 new_modules [module_count] = image;
5093 mono_image_addref (image);
5095 g_free (image->assembly->image->modules);
5096 image->assembly->image->modules = new_modules;
5097 image->assembly->image->module_count ++;
5099 mono_assembly_load_references (image, &status);
5101 mono_image_close (image);
5102 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5105 return mono_module_get_object (mono_domain_get (), image);
5109 * We need to return always the same object for MethodInfo, FieldInfo etc..
5110 * but we need to consider the reflected type.
5111 * type uses a different hash, since it uses custom hash/equal functions.
5116 MonoClass *refclass;
5120 reflected_equal (gconstpointer a, gconstpointer b) {
5121 const ReflectedEntry *ea = a;
5122 const ReflectedEntry *eb = b;
5124 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5128 reflected_hash (gconstpointer a) {
5129 const ReflectedEntry *ea = a;
5130 return mono_aligned_addr_hash (ea->item);
5133 #define CHECK_OBJECT(t,p,k) \
5139 mono_domain_lock (domain); \
5140 if (!domain->refobject_hash) \
5141 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5142 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5143 mono_domain_unlock (domain); \
5146 mono_domain_unlock (domain); \
5150 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5152 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5154 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5157 #define CACHE_OBJECT(t,p,o,k) \
5160 ReflectedEntry pe; \
5162 pe.refclass = (k); \
5163 mono_domain_lock (domain); \
5164 if (!domain->refobject_hash) \
5165 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5166 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5168 ReflectedEntry *e = ALLOC_REFENTRY; \
5170 e->refclass = (k); \
5171 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5174 mono_domain_unlock (domain); \
5179 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5181 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5185 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5187 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5191 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5193 MonoDynamicImage *image = moduleb->dynamic_image;
5194 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5197 MonoImage **new_modules;
5200 * FIXME: we already created an image in mono_image_basic_init (), but
5201 * we don't know which module it belongs to, since that is only
5202 * determined at assembly save time.
5204 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5205 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5207 moduleb->module.image = &image->image;
5208 moduleb->dynamic_image = image;
5209 register_module (mono_object_domain (moduleb), moduleb, image);
5211 /* register the module with the assembly */
5212 ass = ab->dynamic_assembly->assembly.image;
5213 module_count = ass->module_count;
5214 new_modules = g_new0 (MonoImage *, module_count + 1);
5217 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5218 new_modules [module_count] = &image->image;
5219 mono_image_addref (&image->image);
5221 g_free (ass->modules);
5222 ass->modules = new_modules;
5223 ass->module_count ++;
5228 * mono_assembly_get_object:
5229 * @domain: an app domain
5230 * @assembly: an assembly
5232 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5234 MonoReflectionAssembly*
5235 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5237 static MonoClass *System_Reflection_Assembly;
5238 MonoReflectionAssembly *res;
5240 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5241 if (!System_Reflection_Assembly)
5242 System_Reflection_Assembly = mono_class_from_name (
5243 mono_defaults.corlib, "System.Reflection", "Assembly");
5244 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5245 res->assembly = assembly;
5247 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5252 MonoReflectionModule*
5253 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5255 static MonoClass *System_Reflection_Module;
5256 MonoReflectionModule *res;
5259 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5260 if (!System_Reflection_Module)
5261 System_Reflection_Module = mono_class_from_name (
5262 mono_defaults.corlib, "System.Reflection", "Module");
5263 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5266 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5268 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5269 basename = g_path_get_basename (image->name);
5270 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5271 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5275 if (image->assembly->image == image) {
5276 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5280 if (image->assembly->image->modules) {
5281 for (i = 0; i < image->assembly->image->module_count; i++) {
5282 if (image->assembly->image->modules [i] == image)
5283 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5285 g_assert (res->token);
5289 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5292 MonoReflectionModule*
5293 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5295 static MonoClass *System_Reflection_Module;
5296 MonoReflectionModule *res;
5297 MonoTableInfo *table;
5298 guint32 cols [MONO_FILE_SIZE];
5300 guint32 i, name_idx;
5303 if (!System_Reflection_Module)
5304 System_Reflection_Module = mono_class_from_name (
5305 mono_defaults.corlib, "System.Reflection", "Module");
5306 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5308 table = &image->tables [MONO_TABLE_FILE];
5309 g_assert (table_index < table->rows);
5310 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5313 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5314 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5316 /* Check whenever the row has a corresponding row in the moduleref table */
5317 table = &image->tables [MONO_TABLE_MODULEREF];
5318 for (i = 0; i < table->rows; ++i) {
5319 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5320 val = mono_metadata_string_heap (image, name_idx);
5321 if (strcmp (val, name) == 0)
5322 res->image = image->modules [i];
5325 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5326 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5327 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5328 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5329 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5335 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5337 if ((t1->type != t2->type) ||
5338 (t1->byref != t2->byref))
5342 case MONO_TYPE_VOID:
5343 case MONO_TYPE_BOOLEAN:
5344 case MONO_TYPE_CHAR:
5355 case MONO_TYPE_STRING:
5358 case MONO_TYPE_OBJECT:
5359 case MONO_TYPE_TYPEDBYREF:
5361 case MONO_TYPE_VALUETYPE:
5362 case MONO_TYPE_CLASS:
5363 case MONO_TYPE_SZARRAY:
5364 return t1->data.klass == t2->data.klass;
5366 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5367 case MONO_TYPE_ARRAY:
5368 if (t1->data.array->rank != t2->data.array->rank)
5370 return t1->data.array->eklass == t2->data.array->eklass;
5371 case MONO_TYPE_GENERICINST: {
5373 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5375 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5376 &t2->data.generic_class->container_class->byval_arg))
5378 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5379 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5385 case MONO_TYPE_MVAR:
5386 return t1->data.generic_param == t2->data.generic_param;
5388 g_error ("implement type compare for %0x!", t1->type);
5396 mymono_metadata_type_hash (MonoType *t1)
5402 hash |= t1->byref << 6; /* do not collide with t1->type values */
5404 case MONO_TYPE_VALUETYPE:
5405 case MONO_TYPE_CLASS:
5406 case MONO_TYPE_SZARRAY:
5407 /* check if the distribution is good enough */
5408 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5410 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5411 case MONO_TYPE_GENERICINST: {
5413 MonoGenericInst *inst = t1->data.generic_class->inst;
5414 hash += g_str_hash (t1->data.generic_class->container_class->name);
5416 for (i = 0; i < inst->type_argc; ++i) {
5417 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5426 static MonoReflectionGenericClass*
5427 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5429 static MonoClass *System_Reflection_MonoGenericClass;
5430 MonoReflectionGenericClass *res;
5431 MonoInflatedGenericClass *gclass;
5434 if (!System_Reflection_MonoGenericClass) {
5435 System_Reflection_MonoGenericClass = mono_class_from_name (
5436 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5437 g_assert (System_Reflection_MonoGenericClass);
5440 gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
5441 gklass = gclass->generic_class.container_class;
5442 g_assert (gklass->generic_container);
5444 mono_class_init (gclass->klass);
5447 /* FIXME: allow unpinned later */
5448 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5450 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5453 res->type.type = geninst;
5454 if (gklass->wastypebuilder && gklass->reflection_info)
5455 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5457 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5463 verify_safe_for_managed_space (MonoType *type)
5465 switch (type->type) {
5467 case MONO_TYPE_ARRAY:
5468 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5470 return verify_safe_for_managed_space (type->data.type);
5471 case MONO_TYPE_SZARRAY:
5472 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5473 case MONO_TYPE_GENERICINST: {
5474 MonoGenericInst *inst = type->data.generic_class->inst;
5478 for (i = 0; i < inst->type_argc; ++i)
5479 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5485 case MONO_TYPE_MVAR:
5492 * mono_type_get_object:
5493 * @domain: an app domain
5496 * Return an System.MonoType object representing the type @type.
5499 mono_type_get_object (MonoDomain *domain, MonoType *type)
5501 MonoReflectionType *res;
5502 MonoClass *klass = mono_class_from_mono_type (type);
5504 mono_domain_lock (domain);
5505 if (!domain->type_hash)
5506 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5507 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5508 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5509 mono_domain_unlock (domain);
5512 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5513 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5514 mono_g_hash_table_insert (domain->type_hash, type, res);
5515 mono_domain_unlock (domain);
5519 if (!verify_safe_for_managed_space (type)) {
5520 mono_domain_unlock (domain);
5521 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5524 if (klass->reflection_info && !klass->wastypebuilder) {
5525 /* g_assert_not_reached (); */
5526 /* should this be considered an error condition? */
5528 mono_domain_unlock (domain);
5529 return klass->reflection_info;
5532 mono_class_init (klass);
5534 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5536 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5539 mono_g_hash_table_insert (domain->type_hash, type, res);
5540 mono_domain_unlock (domain);
5545 * mono_method_get_object:
5546 * @domain: an app domain
5548 * @refclass: the reflected type (can be NULL)
5550 * Return an System.Reflection.MonoMethod object representing the method @method.
5552 MonoReflectionMethod*
5553 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5556 * We use the same C representation for methods and constructors, but the type
5557 * name in C# is different.
5559 static MonoClass *System_Reflection_MonoMethod = NULL;
5560 static MonoClass *System_Reflection_MonoCMethod = NULL;
5561 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5562 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5565 MonoReflectionMethod *ret;
5567 if (method->is_inflated) {
5568 MonoReflectionGenericMethod *gret;
5570 method = mono_get_inflated_method (method);
5571 refclass = method->klass;
5572 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5573 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5574 if (!System_Reflection_MonoGenericCMethod)
5575 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5576 klass = System_Reflection_MonoGenericCMethod;
5578 if (!System_Reflection_MonoGenericMethod)
5579 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5580 klass = System_Reflection_MonoGenericMethod;
5582 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5583 gret->method.method = method;
5584 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5585 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5586 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5590 refclass = method->klass;
5592 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5593 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5594 if (!System_Reflection_MonoCMethod)
5595 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5596 klass = System_Reflection_MonoCMethod;
5599 if (!System_Reflection_MonoMethod)
5600 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5601 klass = System_Reflection_MonoMethod;
5603 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5604 ret->method = method;
5605 MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name));
5606 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5607 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5611 * mono_field_get_object:
5612 * @domain: an app domain
5616 * Return an System.Reflection.MonoField object representing the field @field
5619 MonoReflectionField*
5620 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5622 MonoReflectionField *res;
5625 CHECK_OBJECT (MonoReflectionField *, field, klass);
5626 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5627 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5630 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5631 if (field->generic_info)
5632 res->attrs = field->generic_info->generic_type->attrs;
5634 res->attrs = field->type->attrs;
5635 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5636 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5640 * mono_property_get_object:
5641 * @domain: an app domain
5643 * @property: a property
5645 * Return an System.Reflection.MonoProperty object representing the property @property
5648 MonoReflectionProperty*
5649 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5651 MonoReflectionProperty *res;
5654 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5655 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5656 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5658 res->property = property;
5659 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5663 * mono_event_get_object:
5664 * @domain: an app domain
5668 * Return an System.Reflection.MonoEvent object representing the event @event
5671 MonoReflectionEvent*
5672 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5674 MonoReflectionEvent *res;
5677 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5678 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5679 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5682 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5686 * mono_param_get_objects:
5687 * @domain: an app domain
5690 * Return an System.Reflection.ParameterInfo array object representing the parameters
5691 * in the method @method.
5694 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5696 static MonoClass *System_Reflection_ParameterInfo;
5697 MonoArray *res = NULL;
5698 MonoReflectionMethod *member = NULL;
5699 MonoReflectionParameter *param = NULL;
5700 char **names, **blobs = NULL;
5701 guint32 *types = NULL;
5702 MonoType *type = NULL;
5703 MonoObject *dbnull = mono_get_dbnull_object (domain);
5704 MonoMarshalSpec **mspecs;
5705 MonoMethodSignature *sig;
5708 if (!System_Reflection_ParameterInfo)
5709 System_Reflection_ParameterInfo = mono_class_from_name (
5710 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5712 if (!mono_method_signature (method)->param_count)
5713 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5715 /* Note: the cache is based on the address of the signature into the method
5716 * since we already cache MethodInfos with the method as keys.
5718 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5720 sig = mono_method_signature (method);
5721 member = mono_method_get_object (domain, method, NULL);
5722 names = g_new (char *, sig->param_count);
5723 mono_method_get_param_names (method, (const char **) names);
5725 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5726 mono_method_get_marshal_info (method, mspecs);
5728 res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5729 for (i = 0; i < sig->param_count; ++i) {
5730 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5731 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5732 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5733 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5734 param->PositionImpl = i;
5735 param->AttrsImpl = sig->params [i]->attrs;
5737 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5738 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5742 blobs = g_new0 (char *, sig->param_count);
5743 types = g_new0 (guint32, sig->param_count);
5744 get_default_param_value_blobs (method, blobs, types);
5747 /* Build MonoType for the type from the Constant Table */
5749 type = g_new0 (MonoType, 1);
5750 type->type = types [i];
5751 type->data.klass = NULL;
5752 if (types [i] == MONO_TYPE_CLASS)
5753 type->data.klass = mono_defaults.object_class;
5754 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5755 /* For enums, types [i] contains the base type */
5757 type->type = MONO_TYPE_VALUETYPE;
5758 type->data.klass = mono_class_from_mono_type (sig->params [i]);
5760 type->data.klass = mono_class_from_mono_type (type);
5762 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5764 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5765 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5766 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5771 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5773 mono_array_setref (res, i, param);
5780 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5782 mono_metadata_free_marshal_spec (mspecs [i]);
5785 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5789 * mono_method_body_get_object:
5790 * @domain: an app domain
5793 * Return an System.Reflection.MethodBody object representing the method @method.
5795 MonoReflectionMethodBody*
5796 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5798 static MonoClass *System_Reflection_MethodBody = NULL;
5799 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5800 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5801 MonoReflectionMethodBody *ret;
5802 MonoMethodNormal *mn;
5803 MonoMethodHeader *header;
5804 guint32 method_rva, local_var_sig_token;
5806 unsigned char format, flags;
5809 if (!System_Reflection_MethodBody)
5810 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5811 if (!System_Reflection_LocalVariableInfo)
5812 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5813 if (!System_Reflection_ExceptionHandlingClause)
5814 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5816 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5818 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5819 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5820 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5821 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5823 mn = (MonoMethodNormal *)method;
5824 header = mono_method_get_header (method);
5826 /* Obtain local vars signature token */
5827 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5828 ptr = mono_image_rva_map (method->klass->image, method_rva);
5829 flags = *(const unsigned char *) ptr;
5830 format = flags & METHOD_HEADER_FORMAT_MASK;
5832 case METHOD_HEADER_TINY_FORMAT:
5833 case METHOD_HEADER_TINY_FORMAT1:
5834 local_var_sig_token = 0;
5836 case METHOD_HEADER_FAT_FORMAT:
5840 local_var_sig_token = read32 (ptr);
5843 g_assert_not_reached ();
5846 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5848 ret->init_locals = header->init_locals;
5849 ret->max_stack = header->max_stack;
5850 ret->local_var_sig_token = local_var_sig_token;
5851 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5852 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5855 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5856 for (i = 0; i < header->num_locals; ++i) {
5857 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5858 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5859 info->is_pinned = header->locals [i]->pinned;
5860 info->local_index = i;
5861 mono_array_setref (ret->locals, i, info);
5865 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5866 for (i = 0; i < header->num_clauses; ++i) {
5867 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5868 MonoExceptionClause *clause = &header->clauses [i];
5870 info->flags = clause->flags;
5871 info->try_offset = clause->try_offset;
5872 info->try_length = clause->try_len;
5873 info->handler_offset = clause->handler_offset;
5874 info->handler_length = clause->handler_len;
5875 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5876 info->filter_offset = clause->data.filter_offset;
5877 else if (clause->data.catch_class)
5878 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5880 mono_array_setref (ret->clauses, i, info);
5883 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5888 mono_get_dbnull_object (MonoDomain *domain)
5892 static MonoClassField *dbnull_value_field = NULL;
5894 if (!dbnull_value_field) {
5895 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5896 mono_class_init (klass);
5897 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5898 g_assert (dbnull_value_field);
5900 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5907 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5909 guint32 param_index, i, lastp, crow = 0;
5910 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5913 MonoClass *klass = method->klass;
5914 MonoImage *image = klass->image;
5915 MonoMethodSignature *methodsig = mono_method_signature (method);
5917 MonoTableInfo *constt;
5918 MonoTableInfo *methodt;
5919 MonoTableInfo *paramt;
5921 if (!methodsig->param_count)
5924 mono_class_init (klass);
5926 if (klass->image->dynamic) {
5927 MonoReflectionMethodAux *aux;
5928 if (method->is_inflated)
5929 method = ((MonoMethodInflated*)method)->declaring;
5930 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5931 if (aux && aux->param_defaults) {
5932 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5933 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5938 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5939 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5940 constt = &image->tables [MONO_TABLE_CONSTANT];
5942 idx = mono_method_get_index (method) - 1;
5943 g_assert (idx != -1);
5945 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5946 if (idx + 1 < methodt->rows)
5947 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5949 lastp = paramt->rows + 1;
5951 for (i = param_index; i < lastp; ++i) {
5954 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5955 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5957 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5960 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5965 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5966 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5967 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5974 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5979 MonoType *basetype = type;
5984 klass = mono_class_from_mono_type (type);
5985 if (klass->valuetype) {
5986 object = mono_object_new (domain, klass);
5987 retval = ((gchar *) object + sizeof (MonoObject));
5988 if (klass->enumtype)
5989 basetype = klass->enum_basetype;
5994 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6001 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6005 memset (assembly, 0, sizeof (MonoAssemblyName));
6007 assembly->culture = "";
6008 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6010 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6013 while (g_ascii_isspace (*p) || *p == ',') {
6022 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6024 assembly->major = strtoul (p, &s, 10);
6025 if (s == p || *s != '.')
6028 assembly->minor = strtoul (p, &s, 10);
6029 if (s == p || *s != '.')
6032 assembly->build = strtoul (p, &s, 10);
6033 if (s == p || *s != '.')
6036 assembly->revision = strtoul (p, &s, 10);
6040 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6042 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6043 assembly->culture = "";
6046 assembly->culture = p;
6047 while (*p && *p != ',') {
6051 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6053 if (strncmp (p, "null", 4) == 0) {
6058 while (*p && *p != ',') {
6061 len = (p - start + 1);
6062 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6063 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6064 g_strlcpy (assembly->public_key_token, start, len);
6067 while (*p && *p != ',')
6071 while (g_ascii_isspace (*p) || *p == ',') {
6085 * mono_reflection_parse_type:
6088 * Parse a type name as accepted by the GetType () method and output the info
6089 * extracted in the info structure.
6090 * the name param will be mangled, so, make a copy before passing it to this function.
6091 * The fields in info will be valid until the memory pointed to by name is valid.
6093 * See also mono_type_get_name () below.
6095 * Returns: 0 on parse error.
6098 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6099 MonoTypeNameParse *info)
6101 char *start, *p, *w, *temp, *last_point, *startn;
6102 int in_modifiers = 0;
6103 int isbyref = 0, rank, arity = 0, i;
6105 start = p = w = name;
6107 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6108 info->name = info->name_space = NULL;
6109 info->nested = NULL;
6110 info->modifiers = NULL;
6111 info->type_arguments = NULL;
6113 /* last_point separates the namespace from the name */
6119 *p = 0; /* NULL terminate the name */
6121 info->nested = g_list_append (info->nested, startn);
6122 /* we have parsed the nesting namespace + name */
6126 info->name_space = start;
6128 info->name = last_point + 1;
6130 info->name_space = (char *)"";
6149 i = strtol (p, &temp, 10);
6166 info->name_space = start;
6168 info->name = last_point + 1;
6170 info->name_space = (char *)"";
6177 if (isbyref) /* only one level allowed by the spec */
6180 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6184 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6190 info->type_arguments = g_ptr_array_new ();
6191 for (i = 0; i < arity; i++) {
6192 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6193 gboolean fqname = FALSE;
6195 g_ptr_array_add (info->type_arguments, subinfo);
6202 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6213 while (*p && (*p != ']'))
6221 if (g_ascii_isspace (*aname)) {
6228 !assembly_name_to_aname (&subinfo->assembly, aname))
6232 if (i + 1 < arity) {
6252 else if (*p != '*') /* '*' means unknown lower bound */
6258 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6269 if (g_ascii_isspace (*p)) {
6276 return 0; /* missing assembly name */
6277 if (!assembly_name_to_aname (&info->assembly, p))
6283 if (info->assembly.name)
6286 // *w = 0; /* terminate class name */
6288 if (!info->name || !*info->name)
6292 /* add other consistency checks */
6297 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6299 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6303 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6305 gboolean type_resolve = FALSE;
6308 if (info->assembly.name) {
6309 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6311 /* then we must load the assembly ourselve - see #60439 */
6312 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6316 image = assembly->image;
6317 } else if (!image) {
6318 image = mono_defaults.corlib;
6321 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6322 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6323 image = mono_defaults.corlib;
6324 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6331 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6338 image = mono_defaults.corlib;
6341 klass = mono_class_from_name_case (image, info->name_space, info->name);
6343 klass = mono_class_from_name (image, info->name_space, info->name);
6346 for (mod = info->nested; mod; mod = mod->next) {
6349 mono_class_init (klass);
6350 nested = klass->nested_classes;
6353 klass = nested->data;
6355 if (g_strcasecmp (klass->name, mod->data) == 0)
6358 if (strcmp (klass->name, mod->data) == 0)
6362 nested = nested->next;
6369 mono_class_init (klass);
6371 if (info->type_arguments) {
6372 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6373 MonoReflectionType *the_type;
6377 for (i = 0; i < info->type_arguments->len; i++) {
6378 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6380 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6381 if (!type_args [i]) {
6387 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6389 instance = mono_reflection_bind_generic_parameters (
6390 the_type, info->type_arguments->len, type_args);
6397 klass = mono_class_from_mono_type (instance);
6400 for (mod = info->modifiers; mod; mod = mod->next) {
6401 modval = GPOINTER_TO_UINT (mod->data);
6402 if (!modval) { /* byref: must be last modifier */
6403 return &klass->this_arg;
6404 } else if (modval == -1) {
6405 klass = mono_ptr_class_get (&klass->byval_arg);
6406 } else { /* array rank */
6407 klass = mono_array_class_get (klass, modval);
6409 mono_class_init (klass);
6412 return &klass->byval_arg;
6416 * mono_reflection_get_type:
6417 * @image: a metadata context
6418 * @info: type description structure
6419 * @ignorecase: flag for case-insensitive string compares
6420 * @type_resolve: whenever type resolve was already tried
6422 * Build a MonoType from the type description in @info.
6427 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6430 MonoReflectionAssembly *assembly;
6434 type = mono_reflection_get_type_internal (image, info, ignorecase);
6437 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6444 *type_resolve = TRUE;
6447 /* Reconstruct the type name */
6448 fullName = g_string_new ("");
6449 if (info->name_space && (info->name_space [0] != '\0'))
6450 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6452 g_string_printf (fullName, info->name);
6453 for (mod = info->nested; mod; mod = mod->next)
6454 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6456 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6458 if (assembly->assembly->dynamic) {
6459 /* Enumerate all modules */
6460 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6464 if (abuilder->modules) {
6465 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6466 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6467 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6473 if (!type && abuilder->loaded_modules) {
6474 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6475 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6476 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6483 type = mono_reflection_get_type_internal (assembly->assembly->image,
6486 g_string_free (fullName, TRUE);
6491 free_type_info (MonoTypeNameParse *info)
6493 g_list_free (info->modifiers);
6494 g_list_free (info->nested);
6496 if (info->type_arguments) {
6499 for (i = 0; i < info->type_arguments->len; i++) {
6500 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6502 free_type_info (subinfo);
6505 g_ptr_array_free (info->type_arguments, TRUE);
6510 * mono_reflection_type_from_name:
6512 * @image: a metadata context (can be NULL).
6514 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6515 * it defaults to get the type from @image or, if @image is NULL or loading
6516 * from it fails, uses corlib.
6520 mono_reflection_type_from_name (char *name, MonoImage *image)
6522 MonoType *type = NULL;
6523 MonoTypeNameParse info;
6526 /* Make a copy since parse_type modifies its argument */
6527 tmp = g_strdup (name);
6529 /*g_print ("requested type %s\n", str);*/
6530 if (mono_reflection_parse_type (tmp, &info)) {
6531 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6535 free_type_info (&info);
6540 * mono_reflection_get_token:
6542 * Return the metadata token of OBJ which should be an object
6543 * representing a metadata element.
6546 mono_reflection_get_token (MonoObject *obj)
6551 klass = obj->vtable->klass;
6553 if (strcmp (klass->name, "MethodBuilder") == 0) {
6554 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6556 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6557 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6558 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6560 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6561 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6562 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6563 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6564 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6565 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6566 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6567 } else if (strcmp (klass->name, "MonoType") == 0) {
6568 MonoReflectionType *tb = (MonoReflectionType *)obj;
6569 token = mono_class_from_mono_type (tb->type)->type_token;
6570 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6571 strcmp (klass->name, "MonoMethod") == 0 ||
6572 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6573 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6574 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6575 if (m->method->is_inflated) {
6576 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6577 return inflated->declaring->token;
6579 token = m->method->token;
6581 } else if (strcmp (klass->name, "MonoField") == 0) {
6582 MonoReflectionField *f = (MonoReflectionField*)obj;
6584 if (f->field->generic_info && f->field->generic_info->reflection_info)
6585 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6587 token = mono_class_get_field_token (f->field);
6588 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6589 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6591 token = mono_class_get_property_token (p->property);
6592 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6593 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6595 token = mono_class_get_event_token (p->event);
6596 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6597 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6599 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6600 } else if (strcmp (klass->name, "Module") == 0) {
6601 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6604 } else if (strcmp (klass->name, "Assembly") == 0) {
6605 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6607 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6608 MonoException *ex = mono_get_exception_not_implemented (msg);
6610 mono_raise_exception (ex);
6617 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6619 int slen, type = t->type;
6620 MonoClass *tklass = t->data.klass;
6626 case MONO_TYPE_BOOLEAN: {
6627 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6632 case MONO_TYPE_CHAR:
6634 case MONO_TYPE_I2: {
6635 guint16 *val = g_malloc (sizeof (guint16));
6640 #if SIZEOF_VOID_P == 4
6646 case MONO_TYPE_I4: {
6647 guint32 *val = g_malloc (sizeof (guint32));
6652 #if SIZEOF_VOID_P == 8
6653 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6658 case MONO_TYPE_I8: {
6659 guint64 *val = g_malloc (sizeof (guint64));
6664 case MONO_TYPE_VALUETYPE:
6665 if (t->data.klass->enumtype) {
6666 type = t->data.klass->enum_basetype->type;
6669 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6672 case MONO_TYPE_STRING:
6673 if (*p == (char)0xFF) {
6677 slen = mono_metadata_decode_value (p, &p);
6679 return mono_string_new_len (mono_domain_get (), p, slen);
6680 case MONO_TYPE_CLASS: {
6683 if (*p == (char)0xFF) {
6688 slen = mono_metadata_decode_value (p, &p);
6689 n = g_memdup (p, slen + 1);
6691 t = mono_reflection_type_from_name (n, image);
6693 g_warning ("Cannot load type '%s'", n);
6697 return mono_type_get_object (mono_domain_get (), t);
6701 case MONO_TYPE_OBJECT: {
6704 MonoClass *subc = NULL;
6709 } else if (subt == 0x0E) {
6710 type = MONO_TYPE_STRING;
6712 } else if (subt == 0x1D) {
6713 MonoType simple_type = {{0}};
6717 type = MONO_TYPE_SZARRAY;
6718 simple_type.type = etype;
6719 tklass = mono_class_from_mono_type (&simple_type);
6721 } else if (subt == 0x55) {
6724 slen = mono_metadata_decode_value (p, &p);
6725 n = g_memdup (p, slen + 1);
6727 t = mono_reflection_type_from_name (n, image);
6729 g_error ("Cannot load type '%s'", n);
6732 subc = mono_class_from_mono_type (t);
6733 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6734 MonoType simple_type = {{0}};
6735 simple_type.type = subt;
6736 subc = mono_class_from_mono_type (&simple_type);
6738 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6740 val = load_cattr_value (image, &subc->byval_arg, p, end);
6741 obj = mono_object_new (mono_domain_get (), subc);
6742 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6746 case MONO_TYPE_SZARRAY: {
6748 guint32 i, alen, basetype;
6751 if (alen == 0xffffffff) {
6755 arr = mono_array_new (mono_domain_get(), tklass, alen);
6756 basetype = tklass->byval_arg.type;
6761 case MONO_TYPE_BOOLEAN:
6762 for (i = 0; i < alen; i++) {
6763 MonoBoolean val = *p++;
6764 mono_array_set (arr, MonoBoolean, i, val);
6767 case MONO_TYPE_CHAR:
6770 for (i = 0; i < alen; i++) {
6771 guint16 val = read16 (p);
6772 mono_array_set (arr, guint16, i, val);
6779 for (i = 0; i < alen; i++) {
6780 guint32 val = read32 (p);
6781 mono_array_set (arr, guint32, i, val);
6788 for (i = 0; i < alen; i++) {
6789 guint64 val = read64 (p);
6790 mono_array_set (arr, guint64, i, val);
6794 case MONO_TYPE_CLASS:
6795 case MONO_TYPE_OBJECT:
6796 case MONO_TYPE_STRING:
6797 for (i = 0; i < alen; i++) {
6798 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6799 mono_array_setref (arr, i, item);
6803 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6809 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6815 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6817 static MonoClass *klass;
6818 static MonoMethod *ctor;
6820 void *params [2], *unboxed;
6823 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6825 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6827 params [0] = mono_type_get_object (mono_domain_get (), t);
6829 retval = mono_object_new (mono_domain_get (), klass);
6830 unboxed = mono_object_unbox (retval);
6831 mono_runtime_invoke (ctor, unboxed, params, NULL);
6837 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6839 static MonoClass *klass;
6840 static MonoMethod *ctor;
6842 void *unboxed, *params [2];
6845 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6847 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6850 params [1] = typedarg;
6851 retval = mono_object_new (mono_domain_get (), klass);
6852 unboxed = mono_object_unbox (retval);
6853 mono_runtime_invoke (ctor, unboxed, params, NULL);
6859 type_is_reference (MonoType *type)
6861 switch (type->type) {
6862 case MONO_TYPE_BOOLEAN:
6863 case MONO_TYPE_CHAR:
6876 case MONO_TYPE_VALUETYPE:
6884 free_param_data (MonoMethodSignature *sig, void **params) {
6886 for (i = 0; i < sig->param_count; ++i) {
6887 if (!type_is_reference (sig->params [i]))
6888 g_free (params [i]);
6893 * Find the field index in the metadata FieldDef table.
6896 find_field_index (MonoClass *klass, MonoClassField *field) {
6899 for (i = 0; i < klass->field.count; ++i) {
6900 if (field == &klass->fields [i])
6901 return klass->field.first + 1 + i;
6907 * Find the property index in the metadata Property table.
6910 find_property_index (MonoClass *klass, MonoProperty *property) {
6913 for (i = 0; i < klass->property.count; ++i) {
6914 if (property == &klass->properties [i])
6915 return klass->property.first + 1 + i;
6921 * Find the event index in the metadata Event table.
6924 find_event_index (MonoClass *klass, MonoEvent *event) {
6927 for (i = 0; i < klass->event.count; ++i) {
6928 if (event == &klass->events [i])
6929 return klass->event.first + 1 + i;
6935 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
6937 const char *p = (const char*)data;
6939 guint32 i, j, num_named;
6943 mono_class_init (method->klass);
6946 attr = mono_object_new (mono_domain_get (), method->klass);
6947 mono_runtime_invoke (method, attr, NULL, NULL);
6951 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6954 /*g_print ("got attr %s\n", method->klass->name);*/
6956 /* Allocate using alloca so it gets GC tracking */
6957 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6961 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6962 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6966 attr = mono_object_new (mono_domain_get (), method->klass);
6967 mono_runtime_invoke (method, attr, params, NULL);
6968 free_param_data (method->signature, params);
6969 num_named = read16 (named);
6971 for (j = 0; j < num_named; j++) {
6973 gboolean is_boxed = FALSE;
6974 char *name, named_type, data_type;
6975 named_type = *named++;
6976 data_type = *named++; /* type of data */
6977 if (data_type == 0x51)
6980 if (data_type == 0x55) {
6983 type_len = mono_metadata_decode_blob_size (named, &named);
6984 type_name = g_malloc (type_len + 1);
6985 memcpy (type_name, named, type_len);
6986 type_name [type_len] = 0;
6988 /* FIXME: lookup the type and check type consistency */
6990 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6991 /* this seems to be the type of the element of the array */
6992 /* g_print ("skipping 0x%02x after prop\n", *named); */
6995 name_len = mono_metadata_decode_blob_size (named, &named);
6996 name = g_malloc (name_len + 1);
6997 memcpy (name, named, name_len);
6998 name [name_len] = 0;
7000 if (named_type == 0x53) {
7001 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7002 void *val = load_cattr_value (image, field->type, named, &named);
7003 mono_field_set_value (attr, field, val);
7004 if (!type_is_reference (field->type))
7006 } else if (named_type == 0x54) {
7009 MonoType *prop_type;
7011 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7012 /* can we have more that 1 arg in a custom attr named property? */
7013 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7014 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7015 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7016 mono_property_set_value (prop, attr, pparams, NULL);
7017 if (!type_is_reference (prop_type))
7018 g_free (pparams [0]);
7027 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7029 MonoArray *typedargs, *namedargs;
7030 MonoClass *attrklass;
7031 static MonoClass *klass;
7032 static MonoMethod *ctor;
7035 const char *p = (const char*)data;
7037 guint32 i, j, num_named;
7040 mono_class_init (method->klass);
7043 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7045 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
7047 domain = mono_domain_get ();
7049 /* This is for Attributes with no parameters */
7050 attr = mono_object_new (domain, klass);
7051 params [0] = mono_method_get_object (domain, method, NULL);
7052 params [1] = params [2] = NULL;
7053 mono_runtime_invoke (method, attr, params, NULL);
7057 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7060 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7064 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7065 MonoObject *obj, *typedarg;
7068 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7069 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7070 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7071 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7072 mono_array_setref (typedargs, i, typedarg);
7074 if (!type_is_reference (mono_method_signature (method)->params [i]))
7079 num_named = read16 (named);
7080 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7082 attrklass = method->klass;
7083 for (j = 0; j < num_named; j++) {
7085 char *name, named_type, data_type;
7086 named_type = *named++;
7087 data_type = *named++; /* type of data */
7088 if (data_type == 0x55) {
7091 type_len = mono_metadata_decode_blob_size (named, &named);
7092 type_name = g_malloc (type_len + 1);
7093 memcpy (type_name, named, type_len);
7094 type_name [type_len] = 0;
7096 /* FIXME: lookup the type and check type consistency */
7098 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
7099 /* this seems to be the type of the element of the array */
7100 /* g_print ("skipping 0x%02x after prop\n", *named); */
7103 name_len = mono_metadata_decode_blob_size (named, &named);
7104 name = g_malloc (name_len + 1);
7105 memcpy (name, named, name_len);
7106 name [name_len] = 0;
7108 if (named_type == 0x53) {
7109 MonoObject *obj, *typedarg, *namedarg;
7110 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7111 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7113 minfo = mono_field_get_object (domain, NULL, field);
7114 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7115 typedarg = create_cattr_typed_arg (field->type, obj);
7116 namedarg = create_cattr_named_arg (minfo, typedarg);
7117 mono_array_setref (namedargs, j, namedarg);
7118 if (!type_is_reference (field->type))
7120 } else if (named_type == 0x54) {
7121 MonoObject *obj, *typedarg, *namedarg;
7122 MonoType *prop_type;
7124 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7126 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7127 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7128 minfo = mono_property_get_object (domain, NULL, prop);
7129 val = load_cattr_value (image, prop_type, named, &named);
7130 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7131 typedarg = create_cattr_typed_arg (prop_type, obj);
7132 namedarg = create_cattr_named_arg (minfo, typedarg);
7133 mono_array_setref (namedargs, j, namedarg);
7134 if (!type_is_reference (prop_type))
7139 attr = mono_object_new (domain, klass);
7140 params [0] = mono_method_get_object (domain, method, NULL);
7141 params [1] = typedargs;
7142 params [2] = namedargs;
7143 mono_runtime_invoke (ctor, attr, params, NULL);
7148 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7155 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7156 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7157 for (i = 0; i < cinfo->num_attrs; ++i) {
7158 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7159 mono_array_setref (result, i, attr);
7165 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7173 for (i = 0; i < cinfo->num_attrs; ++i) {
7174 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7178 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7179 result = mono_array_new (mono_domain_get (), klass, n);
7181 for (i = 0; i < cinfo->num_attrs; ++i) {
7182 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7183 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7184 mono_array_setref (result, n, attr);
7192 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7195 static MonoClass *klass;
7200 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7202 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7203 for (i = 0; i < cinfo->num_attrs; ++i) {
7204 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7205 mono_array_setref (result, i, attr);
7211 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7213 guint32 mtoken, i, len;
7214 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7216 MonoCustomAttrInfo *ainfo;
7217 GList *tmp, *list = NULL;
7220 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7222 i = mono_metadata_custom_attrs_from_index (image, idx);
7226 while (i < ca->rows) {
7227 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7229 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7232 len = g_list_length (list);
7235 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7236 ainfo->num_attrs = len;
7237 ainfo->image = image;
7238 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7239 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7240 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7241 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7242 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7243 mtoken |= MONO_TOKEN_METHOD_DEF;
7245 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7246 mtoken |= MONO_TOKEN_MEMBER_REF;
7249 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7252 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7253 if (!ainfo->attrs [i].ctor)
7254 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7255 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7256 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7257 ainfo->attrs [i].data = (guchar*)data;
7265 mono_custom_attrs_from_method (MonoMethod *method)
7267 MonoCustomAttrInfo *cinfo;
7270 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7272 idx = mono_method_get_index (method);
7273 idx <<= MONO_CUSTOM_ATTR_BITS;
7274 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7275 return mono_custom_attrs_from_index (method->klass->image, idx);
7279 mono_custom_attrs_from_class (MonoClass *klass)
7281 MonoCustomAttrInfo *cinfo;
7284 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7286 idx = mono_metadata_token_index (klass->type_token);
7287 idx <<= MONO_CUSTOM_ATTR_BITS;
7288 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7289 return mono_custom_attrs_from_index (klass->image, idx);
7293 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7295 MonoCustomAttrInfo *cinfo;
7298 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7300 idx = 1; /* there is only one assembly */
7301 idx <<= MONO_CUSTOM_ATTR_BITS;
7302 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7303 return mono_custom_attrs_from_index (assembly->image, idx);
7306 static MonoCustomAttrInfo*
7307 mono_custom_attrs_from_module (MonoImage *image)
7309 MonoCustomAttrInfo *cinfo;
7312 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7314 idx = 1; /* there is only one module */
7315 idx <<= MONO_CUSTOM_ATTR_BITS;
7316 idx |= MONO_CUSTOM_ATTR_MODULE;
7317 return mono_custom_attrs_from_index (image, idx);
7321 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7323 MonoCustomAttrInfo *cinfo;
7326 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7328 idx = find_property_index (klass, property);
7329 idx <<= MONO_CUSTOM_ATTR_BITS;
7330 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7331 return mono_custom_attrs_from_index (klass->image, idx);
7335 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7337 MonoCustomAttrInfo *cinfo;
7340 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7342 idx = find_event_index (klass, event);
7343 idx <<= MONO_CUSTOM_ATTR_BITS;
7344 idx |= MONO_CUSTOM_ATTR_EVENT;
7345 return mono_custom_attrs_from_index (klass->image, idx);
7349 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7351 MonoCustomAttrInfo *cinfo;
7354 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7356 idx = find_field_index (klass, field);
7357 idx <<= MONO_CUSTOM_ATTR_BITS;
7358 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7359 return mono_custom_attrs_from_index (klass->image, idx);
7363 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7366 guint32 i, idx, method_index;
7367 guint32 param_list, param_last, param_pos, found;
7369 MonoReflectionMethodAux *aux;
7371 if (method->klass->image->dynamic) {
7372 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7373 if (!aux || !aux->param_cattr)
7375 return aux->param_cattr [param];
7378 image = method->klass->image;
7379 method_index = mono_method_get_index (method);
7380 ca = &image->tables [MONO_TABLE_METHOD];
7382 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7383 if (method_index == ca->rows) {
7384 ca = &image->tables [MONO_TABLE_PARAM];
7385 param_last = ca->rows + 1;
7387 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7388 ca = &image->tables [MONO_TABLE_PARAM];
7391 for (i = param_list; i < param_last; ++i) {
7392 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7393 if (param_pos == param) {
7401 idx <<= MONO_CUSTOM_ATTR_BITS;
7402 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7403 return mono_custom_attrs_from_index (image, idx);
7407 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7411 for (i = 0; i < ainfo->num_attrs; ++i) {
7412 klass = ainfo->attrs [i].ctor->klass;
7413 if (mono_class_has_parent (klass, attr_klass))
7420 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7427 for (i = 0; i < ainfo->num_attrs; ++i) {
7428 klass = ainfo->attrs [i].ctor->klass;
7429 if (mono_class_has_parent (klass, attr_klass)) {
7434 if (attr_index == -1)
7437 attrs = mono_custom_attrs_construct (ainfo);
7439 return mono_array_get (attrs, MonoObject*, attr_index);
7445 * mono_reflection_get_custom_attrs_info:
7446 * @obj: a reflection object handle
7448 * Return the custom attribute info for attributes defined for the
7449 * reflection handle @obj. The objects.
7452 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7455 MonoCustomAttrInfo *cinfo = NULL;
7457 klass = obj->vtable->klass;
7458 if (klass == mono_defaults.monotype_class) {
7459 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7460 klass = mono_class_from_mono_type (rtype->type);
7461 cinfo = mono_custom_attrs_from_class (klass);
7462 } else if (strcmp ("Assembly", klass->name) == 0) {
7463 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7464 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7465 } else if (strcmp ("Module", klass->name) == 0) {
7466 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7467 cinfo = mono_custom_attrs_from_module (module->image);
7468 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7469 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7470 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7471 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7472 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7473 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7474 } else if (strcmp ("MonoField", klass->name) == 0) {
7475 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7476 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7477 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7478 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7479 cinfo = mono_custom_attrs_from_method (rmethod->method);
7480 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7481 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7482 cinfo = mono_custom_attrs_from_method (method);
7483 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7484 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7485 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7486 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7487 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7488 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7489 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7490 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7491 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7492 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7493 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7494 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7495 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7496 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7497 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7498 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7499 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7500 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7501 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7502 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7503 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7504 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7505 } else { /* handle other types here... */
7506 g_error ("get custom attrs not yet supported for %s", klass->name);
7513 * mono_reflection_get_custom_attrs_by_type:
7514 * @obj: a reflection object handle
7516 * Return an array with all the custom attributes defined of the
7517 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7518 * of that type are returned. The objects are fully build.
7521 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7524 MonoCustomAttrInfo *cinfo;
7526 cinfo = mono_reflection_get_custom_attrs_info (obj);
7529 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7531 result = mono_custom_attrs_construct (cinfo);
7533 mono_custom_attrs_free (cinfo);
7536 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7537 result = mono_array_new (mono_domain_get (), klass, 0);
7544 * mono_reflection_get_custom_attrs:
7545 * @obj: a reflection object handle
7547 * Return an array with all the custom attributes defined of the
7548 * reflection handle @obj. The objects are fully build.
7551 mono_reflection_get_custom_attrs (MonoObject *obj)
7553 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7557 * mono_reflection_get_custom_attrs_data:
7558 * @obj: a reflection obj handle
7560 * Returns an array of System.Reflection.CustomAttributeData,
7561 * which include information about attributes reflected on
7562 * types loaded using the Reflection Only methods
7565 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7568 MonoCustomAttrInfo *cinfo;
7570 cinfo = mono_reflection_get_custom_attrs_info (obj);
7572 result = mono_custom_attrs_data_construct (cinfo);
7574 mono_custom_attrs_free (cinfo);
7577 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7578 result = mono_array_new (mono_domain_get (), klass, 0);
7585 * LOCKING: Assumes the loader lock is held.
7587 static MonoMethodSignature*
7588 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7589 MonoMethodSignature *sig;
7592 count = parameters? mono_array_length (parameters): 0;
7594 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7595 sig->param_count = count;
7596 sig->sentinelpos = -1; /* FIXME */
7597 for (i = 0; i < count; ++i) {
7598 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7599 sig->params [i] = pt->type;
7605 * LOCKING: Assumes the loader lock is held.
7607 static MonoMethodSignature*
7608 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7609 MonoMethodSignature *sig;
7611 sig = parameters_to_signature (mp, ctor->parameters);
7612 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7613 sig->ret = &mono_defaults.void_class->byval_arg;
7618 * LOCKING: Assumes the loader lock is held.
7620 static MonoMethodSignature*
7621 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7622 MonoMethodSignature *sig;
7624 sig = parameters_to_signature (mp, method->parameters);
7625 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7626 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7627 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7631 static MonoMethodSignature*
7632 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7633 MonoMethodSignature *sig;
7635 sig = parameters_to_signature (NULL, method->parameters);
7636 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7637 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7638 sig->generic_param_count = 0;
7643 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7645 MonoClass *klass = mono_object_class (prop);
7646 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7647 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7648 *name = mono_string_to_utf8 (pb->name);
7649 *type = pb->type->type;
7651 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7652 *name = g_strdup (p->property->name);
7653 if (p->property->get)
7654 *type = mono_method_signature (p->property->get)->ret;
7656 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7661 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7663 MonoClass *klass = mono_object_class (field);
7664 if (strcmp (klass->name, "FieldBuilder") == 0) {
7665 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7666 *name = mono_string_to_utf8 (fb->name);
7667 *type = fb->type->type;
7669 MonoReflectionField *f = (MonoReflectionField *)field;
7670 *name = g_strdup (f->field->name);
7671 *type = f->field->type;
7676 * Encode a value in a custom attribute stream of bytes.
7677 * The value to encode is either supplied as an object in argument val
7678 * (valuetypes are boxed), or as a pointer to the data in the
7680 * @type represents the type of the value
7681 * @buffer is the start of the buffer
7682 * @p the current position in the buffer
7683 * @buflen contains the size of the buffer and is used to return the new buffer size
7684 * if this needs to be realloced.
7685 * @retbuffer and @retp return the start and the position of the buffer
7688 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7690 MonoTypeEnum simple_type;
7692 if ((p-buffer) + 10 >= *buflen) {
7695 newbuf = g_realloc (buffer, *buflen);
7696 p = newbuf + (p-buffer);
7700 argval = ((char*)arg + sizeof (MonoObject));
7701 simple_type = type->type;
7703 switch (simple_type) {
7704 case MONO_TYPE_BOOLEAN:
7709 case MONO_TYPE_CHAR:
7712 swap_with_size (p, argval, 2, 1);
7718 swap_with_size (p, argval, 4, 1);
7724 swap_with_size (p, argval, 8, 1);
7727 case MONO_TYPE_VALUETYPE:
7728 if (type->data.klass->enumtype) {
7729 simple_type = type->data.klass->enum_basetype->type;
7732 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7735 case MONO_TYPE_STRING: {
7742 str = mono_string_to_utf8 ((MonoString*)arg);
7743 slen = strlen (str);
7744 if ((p-buffer) + 10 + slen >= *buflen) {
7748 newbuf = g_realloc (buffer, *buflen);
7749 p = newbuf + (p-buffer);
7752 mono_metadata_encode_value (slen, p, &p);
7753 memcpy (p, str, slen);
7758 case MONO_TYPE_CLASS: {
7766 k = mono_object_class (arg);
7767 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7768 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7769 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
7771 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7772 slen = strlen (str);
7773 if ((p-buffer) + 10 + slen >= *buflen) {
7777 newbuf = g_realloc (buffer, *buflen);
7778 p = newbuf + (p-buffer);
7781 mono_metadata_encode_value (slen, p, &p);
7782 memcpy (p, str, slen);
7787 case MONO_TYPE_SZARRAY: {
7789 MonoClass *eclass, *arg_eclass;
7792 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7795 len = mono_array_length ((MonoArray*)arg);
7797 *p++ = (len >> 8) & 0xff;
7798 *p++ = (len >> 16) & 0xff;
7799 *p++ = (len >> 24) & 0xff;
7801 *retbuffer = buffer;
7802 eclass = type->data.klass;
7803 arg_eclass = mono_object_class (arg)->element_class;
7806 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7807 eclass = mono_defaults.object_class;
7809 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7810 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7811 int elsize = mono_class_array_element_size (arg_eclass);
7812 for (i = 0; i < len; ++i) {
7813 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7816 } else if (eclass->valuetype && arg_eclass->valuetype) {
7817 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7818 int elsize = mono_class_array_element_size (eclass);
7819 for (i = 0; i < len; ++i) {
7820 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7824 for (i = 0; i < len; ++i) {
7825 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7830 case MONO_TYPE_OBJECT: {
7836 * The parameter type is 'object' but the type of the actual
7837 * argument is not. So we have to add type information to the blob
7838 * too. This is completely undocumented in the spec.
7842 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7847 klass = mono_object_class (arg);
7849 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7852 } else if (klass->enumtype) {
7854 } else if (klass == mono_defaults.string_class) {
7855 simple_type = MONO_TYPE_STRING;
7858 } else if (klass->rank == 1) {
7859 simple_type = MONO_TYPE_SZARRAY;
7861 *p++ = klass->element_class->byval_arg.type;
7863 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7864 *p++ = simple_type = klass->byval_arg.type;
7867 g_error ("unhandled type in custom attr");
7869 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7870 slen = strlen (str);
7871 if ((p-buffer) + 10 + slen >= *buflen) {
7875 newbuf = g_realloc (buffer, *buflen);
7876 p = newbuf + (p-buffer);
7879 mono_metadata_encode_value (slen, p, &p);
7880 memcpy (p, str, slen);
7883 simple_type = klass->enum_basetype->type;
7887 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7890 *retbuffer = buffer;
7894 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
7896 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7897 char *str = type_get_qualified_name (type, NULL);
7898 int slen = strlen (str);
7902 * This seems to be optional...
7905 mono_metadata_encode_value (slen, p, &p);
7906 memcpy (p, str, slen);
7909 } else if (type->type == MONO_TYPE_OBJECT) {
7911 } else if (type->type == MONO_TYPE_CLASS) {
7912 /* it should be a type: encode_cattr_value () has the check */
7915 mono_metadata_encode_value (type->type, p, &p);
7916 if (type->type == MONO_TYPE_SZARRAY)
7917 /* See the examples in Partition VI, Annex B */
7918 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
7925 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7928 /* Preallocate a large enough buffer */
7929 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7930 char *str = type_get_qualified_name (type, NULL);
7933 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
7934 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
7940 len += strlen (name);
7942 if ((p-buffer) + 20 + len >= *buflen) {
7946 newbuf = g_realloc (buffer, *buflen);
7947 p = newbuf + (p-buffer);
7951 encode_field_or_prop_type (type, p, &p);
7953 len = strlen (name);
7954 mono_metadata_encode_value (len, p, &p);
7955 memcpy (p, name, len);
7957 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7959 *retbuffer = buffer;
7963 * mono_reflection_get_custom_attrs_blob:
7964 * @ctor: custom attribute constructor
7965 * @ctorArgs: arguments o the constructor
7971 * Creates the blob of data that needs to be saved in the metadata and that represents
7972 * the custom attributed described by @ctor, @ctorArgs etc.
7973 * Returns: a Byte array representing the blob of data.
7976 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7979 MonoMethodSignature *sig;
7984 MONO_ARCH_SAVE_REGS;
7986 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7987 /* sig is freed later so allocate it in the heap */
7988 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
7990 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7993 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7995 p = buffer = g_malloc (buflen);
7996 /* write the prolog */
7999 for (i = 0; i < sig->param_count; ++i) {
8000 arg = mono_array_get (ctorArgs, MonoObject*, i);
8001 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8005 i += mono_array_length (properties);
8007 i += mono_array_length (fields);
8009 *p++ = (i >> 8) & 0xff;
8012 for (i = 0; i < mono_array_length (properties); ++i) {
8016 prop = mono_array_get (properties, gpointer, i);
8017 get_prop_name_and_type (prop, &pname, &ptype);
8018 *p++ = 0x54; /* PROPERTY signature */
8019 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8026 for (i = 0; i < mono_array_length (fields); ++i) {
8030 field = mono_array_get (fields, gpointer, i);
8031 get_field_name_and_type (field, &fname, &ftype);
8032 *p++ = 0x53; /* FIELD signature */
8033 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8038 g_assert (p - buffer <= buflen);
8039 buflen = p - buffer;
8040 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8041 p = mono_array_addr (result, char, 0);
8042 memcpy (p, buffer, buflen);
8044 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8050 static void* reflection_info_desc = NULL;
8054 * mono_reflection_setup_internal_class:
8055 * @tb: a TypeBuilder object
8057 * Creates a MonoClass that represents the TypeBuilder.
8058 * This is a trick that lets us simplify a lot of reflection code
8059 * (and will allow us to support Build and Run assemblies easier).
8062 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8064 MonoClass *klass, *parent;
8066 MONO_ARCH_SAVE_REGS;
8068 mono_loader_lock ();
8071 /* check so we can compile corlib correctly */
8072 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8073 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8074 parent = tb->parent->type->data.klass;
8076 parent = my_mono_class_from_mono_type (tb->parent->type);
8082 /* the type has already being created: it means we just have to change the parent */
8083 if (tb->type.type) {
8084 klass = mono_class_from_mono_type (tb->type.type);
8085 klass->parent = NULL;
8086 /* fool mono_class_setup_parent */
8087 klass->supertypes = NULL;
8088 mono_class_setup_parent (klass, parent);
8089 mono_class_setup_mono_type (klass);
8090 mono_loader_unlock ();
8094 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8096 klass->image = &tb->module->dynamic_image->image;
8098 klass->inited = 1; /* we lie to the runtime */
8099 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8100 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8101 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8102 klass->flags = tb->attrs;
8104 klass->element_class = klass;
8107 if (!reflection_info_desc) {
8109 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);
8111 mono_gc_register_root (&klass->reflection_info, sizeof (gpointer), reflection_info_desc);
8113 klass->reflection_info = tb;
8115 /* Put into cache so mono_class_get () will find it */
8116 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8118 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8119 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8121 if (parent != NULL) {
8122 mono_class_setup_parent (klass, parent);
8123 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8124 const char *old_n = klass->name;
8125 /* trick to get relative numbering right when compiling corlib */
8126 klass->name = "BuildingObject";
8127 mono_class_setup_parent (klass, mono_defaults.object_class);
8128 klass->name = old_n;
8131 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8132 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8133 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8134 klass->instance_size = sizeof (MonoObject);
8135 klass->size_inited = 1;
8136 mono_class_setup_vtable_general (klass, NULL, 0);
8139 mono_class_setup_mono_type (klass);
8141 mono_class_setup_supertypes (klass);
8144 * FIXME: handle interfaces.
8147 tb->type.type = &klass->byval_arg;
8149 if (tb->nesting_type) {
8150 g_assert (tb->nesting_type->type);
8151 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8154 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8156 mono_loader_unlock ();
8160 * mono_reflection_setup_generic_class:
8161 * @tb: a TypeBuilder object
8163 * Setup the generic class before adding the first generic parameter.
8166 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8170 MONO_ARCH_SAVE_REGS;
8172 klass = my_mono_class_from_mono_type (tb->type.type);
8173 if (tb->generic_container)
8176 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8177 tb->generic_container->klass = klass;
8179 tb->generic_container->context.container = tb->generic_container;
8183 * mono_reflection_create_generic_class:
8184 * @tb: a TypeBuilder object
8186 * Creates the generic class after all generic parameters have been added.
8189 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8194 MONO_ARCH_SAVE_REGS;
8196 klass = my_mono_class_from_mono_type (tb->type.type);
8198 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8200 if (klass->generic_container || (count == 0))
8203 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
8205 klass->generic_container = tb->generic_container;
8207 klass->generic_container->type_argc = count;
8208 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8210 for (i = 0; i < count; i++) {
8211 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8212 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8213 g_assert (klass->generic_container->type_params [i].owner);
8216 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
8220 * mono_reflection_create_internal_class:
8221 * @tb: a TypeBuilder object
8223 * Actually create the MonoClass that is associated with the TypeBuilder.
8226 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8230 MONO_ARCH_SAVE_REGS;
8232 klass = my_mono_class_from_mono_type (tb->type.type);
8234 mono_loader_lock ();
8235 if (klass->enumtype && klass->enum_basetype == NULL) {
8236 MonoReflectionFieldBuilder *fb;
8239 g_assert (tb->fields != NULL);
8240 g_assert (mono_array_length (tb->fields) >= 1);
8242 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8244 klass->enum_basetype = fb->type->type;
8245 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8246 if (!klass->element_class)
8247 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8250 * get the element_class from the current corlib.
8252 ec = default_class_from_mono_type (klass->enum_basetype);
8253 klass->instance_size = ec->instance_size;
8254 klass->size_inited = 1;
8256 * this is almost safe to do with enums and it's needed to be able
8257 * to create objects of the enum type (for use in SetConstant).
8259 /* FIXME: Does this mean enums can't have method overrides ? */
8260 mono_class_setup_vtable_general (klass, NULL, 0);
8262 mono_loader_unlock ();
8265 static MonoMarshalSpec*
8266 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8267 MonoReflectionMarshal *minfo)
8269 MonoMarshalSpec *res;
8271 res = g_new0 (MonoMarshalSpec, 1);
8272 res->native = minfo->type;
8274 switch (minfo->type) {
8275 case MONO_NATIVE_LPARRAY:
8276 res->data.array_data.elem_type = minfo->eltype;
8277 if (minfo->has_size) {
8278 res->data.array_data.param_num = minfo->param_num;
8279 res->data.array_data.num_elem = minfo->count;
8280 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8283 res->data.array_data.param_num = -1;
8284 res->data.array_data.num_elem = -1;
8285 res->data.array_data.elem_mult = -1;
8289 case MONO_NATIVE_BYVALTSTR:
8290 case MONO_NATIVE_BYVALARRAY:
8291 res->data.array_data.num_elem = minfo->count;
8294 case MONO_NATIVE_CUSTOM:
8295 if (minfo->marshaltyperef)
8296 res->data.custom_data.custom_name =
8297 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8299 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8309 MonoReflectionMarshal*
8310 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8311 MonoMarshalSpec *spec)
8313 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8314 MonoReflectionMarshal *minfo;
8317 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8318 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8319 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8320 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8323 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8324 minfo->type = spec->native;
8326 switch (minfo->type) {
8327 case MONO_NATIVE_LPARRAY:
8328 minfo->eltype = spec->data.array_data.elem_type;
8329 minfo->count = spec->data.array_data.num_elem;
8330 minfo->param_num = spec->data.array_data.param_num;
8333 case MONO_NATIVE_BYVALTSTR:
8334 case MONO_NATIVE_BYVALARRAY:
8335 minfo->count = spec->data.array_data.num_elem;
8338 case MONO_NATIVE_CUSTOM:
8339 if (spec->data.custom_data.custom_name) {
8340 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8342 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8344 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8346 if (spec->data.custom_data.cookie)
8347 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8358 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8359 ReflectionMethodBuilder *rmb,
8360 MonoMethodSignature *sig)
8363 MonoMethodNormal *pm;
8364 MonoMarshalSpec **specs;
8365 MonoReflectionMethodAux *method_aux;
8370 g_assert (!klass->generic_class);
8373 * Methods created using a MethodBuilder should have their memory allocated
8374 * inside the image mempool, while dynamic methods should have their memory
8377 dynamic = rmb->refs != NULL;
8378 mp = dynamic ? NULL : klass->image->mempool;
8380 mono_loader_lock ();
8382 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8383 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8384 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8386 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8388 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8390 pm = (MonoMethodNormal*)m;
8393 m->flags = rmb->attrs;
8394 m->iflags = rmb->iattrs;
8395 m->name = dynamic ? mono_string_to_utf8 (rmb->name) : mono_string_to_utf8_mp (mp, rmb->name);
8398 m->skip_visibility = rmb->skip_visibility;
8400 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8402 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8403 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8406 m->signature->pinvoke = 1;
8407 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8408 m->signature->pinvoke = 1;
8410 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8412 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8413 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8415 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8417 if (klass->image->dynamic)
8418 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8420 mono_loader_unlock ();
8423 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8424 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8425 MonoMethodHeader *header;
8427 gint32 max_stack, i;
8428 gint32 num_locals = 0;
8429 gint32 num_clauses = 0;
8433 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8434 code_size = rmb->ilgen->code_len;
8435 max_stack = rmb->ilgen->max_stack;
8436 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8437 if (rmb->ilgen->ex_handlers)
8438 num_clauses = method_count_clauses (rmb->ilgen);
8441 code = mono_array_addr (rmb->code, guint8, 0);
8442 code_size = mono_array_length (rmb->code);
8443 /* we probably need to run a verifier on the code... */
8453 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8454 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8455 header->code_size = code_size;
8456 header->code = mp_g_malloc (mp, code_size);
8457 memcpy ((char*)header->code, code, code_size);
8458 header->max_stack = max_stack;
8459 header->init_locals = rmb->init_locals;
8460 header->num_locals = num_locals;
8462 for (i = 0; i < num_locals; ++i) {
8463 MonoReflectionLocalBuilder *lb =
8464 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8466 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8467 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8470 header->num_clauses = num_clauses;
8472 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8473 rmb->ilgen, num_clauses);
8476 pm->header = header;
8479 if (rmb->generic_params) {
8480 int count = mono_array_length (rmb->generic_params);
8481 MonoGenericContainer *container;
8482 MonoGenericContext *context;
8484 m->generic_container = container = rmb->generic_container;
8485 container->type_argc = count;
8486 container->type_params = g_new0 (MonoGenericParam, count);
8488 for (i = 0; i < count; i++) {
8489 MonoReflectionGenericParam *gp =
8490 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8492 container->type_params [i] = *gp->type.type->data.generic_param;
8493 container->type_params [i].method = m;
8496 context = &container->context;
8497 context->container = container;
8498 if (klass->generic_container) {
8499 container->parent = klass->generic_container;
8500 context->gclass = klass->generic_container->context.gclass;
8502 context->gmethod = mono_get_shared_generic_method (container);
8506 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8510 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8512 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8513 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8514 for (i = 0; i < rmb->nrefs; ++i)
8515 data [i + 1] = rmb->refs [i];
8520 /* Parameter info */
8523 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8524 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8525 for (i = 0; i <= m->signature->param_count; ++i) {
8526 MonoReflectionParamBuilder *pb;
8527 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8528 if ((i > 0) && (pb->attrs)) {
8529 /* Make a copy since it might point to a shared type structure */
8530 /* FIXME: Alloc this from a mempool */
8531 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)));
8532 m->signature->params [i - 1]->attrs = pb->attrs;
8535 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8536 MonoDynamicImage *assembly;
8537 guint32 idx, def_type, len;
8541 if (!method_aux->param_defaults) {
8542 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8543 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8545 assembly = (MonoDynamicImage*)klass->image;
8546 idx = encode_constant (assembly, pb->def_value, &def_type);
8547 /* Copy the data from the blob since it might get realloc-ed */
8548 p = assembly->blob.data + idx;
8549 len = mono_metadata_decode_blob_size (p, &p2);
8551 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8552 method_aux->param_default_types [i] = def_type;
8553 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8557 method_aux->param_names [i] = dynamic ? mono_string_to_utf8 (pb->name) : mono_string_to_utf8_mp (mp, pb->name);
8559 if (!method_aux->param_cattr)
8560 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8561 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8567 /* Parameter marshalling */
8570 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8571 MonoReflectionParamBuilder *pb;
8572 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8573 if (pb->marshal_info) {
8575 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8576 specs [pb->position] =
8577 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8581 if (specs != NULL) {
8583 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8584 method_aux->param_marshall = specs;
8587 if (klass->image->dynamic && method_aux)
8588 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8590 mono_loader_unlock ();
8596 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8598 ReflectionMethodBuilder rmb;
8599 MonoMethodSignature *sig;
8601 mono_loader_lock ();
8602 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8603 mono_loader_unlock ();
8605 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8607 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8608 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8610 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8611 /* ilgen is no longer needed */
8619 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8621 ReflectionMethodBuilder rmb;
8622 MonoMethodSignature *sig;
8624 mono_loader_lock ();
8625 sig = method_builder_to_signature (klass->image->mempool, mb);
8626 mono_loader_unlock ();
8628 reflection_methodbuilder_from_method_builder (&rmb, mb);
8630 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8631 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8633 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8634 /* ilgen is no longer needed */
8640 static MonoClassField*
8641 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8643 MonoClassField *field;
8647 field = g_new0 (MonoClassField, 1);
8649 field->name = mono_string_to_utf8 (fb->name);
8651 /* FIXME: handle type modifiers */
8652 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8653 field->type->attrs = fb->attrs;
8655 field->type = fb->type->type;
8657 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8658 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8659 if (fb->offset != -1)
8660 field->offset = fb->offset;
8661 field->parent = klass;
8662 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8664 if (fb->def_value) {
8665 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8666 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8667 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8668 /* Copy the data from the blob since it might get realloc-ed */
8669 p = assembly->blob.data + idx;
8670 len = mono_metadata_decode_blob_size (p, &p2);
8672 field->data = g_malloc (len);
8673 memcpy ((gpointer)field->data, p, len);
8680 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8683 MonoReflectionTypeBuilder *tb = NULL;
8684 MonoGenericClass *gclass, *cached;
8685 gboolean is_dynamic = FALSE;
8690 mono_loader_lock ();
8692 domain = mono_object_domain (type);
8694 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8695 tb = (MonoReflectionTypeBuilder *) type;
8698 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8699 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8700 MonoReflectionType *rgt = rgi->generic_type;
8702 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8703 tb = (MonoReflectionTypeBuilder *) rgt;
8708 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
8709 if (tb && tb->generic_container)
8710 mono_reflection_create_generic_class (tb);
8712 klass = mono_class_from_mono_type (type->type);
8713 if (!klass->generic_container) {
8714 mono_loader_unlock ();
8718 if (klass->wastypebuilder) {
8719 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8725 MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
8726 MonoInflatedGenericClass *igclass = &dgclass->generic_class;
8727 gclass = &igclass->generic_class;
8728 gclass->is_dynamic = TRUE;
8729 gclass->is_inflated = TRUE;
8731 MonoInflatedGenericClass *igclass = g_new0 (MonoInflatedGenericClass, 1);
8732 gclass = &igclass->generic_class;
8733 gclass->is_inflated = TRUE;
8736 gclass->inst = g_new0 (MonoGenericInst, 1);
8738 gclass->inst->type_argc = type_argc;
8739 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8740 gclass->inst->is_reference = 1;
8742 for (i = 0; i < gclass->inst->type_argc; ++i) {
8743 MonoType *t = dup_type (types [i]);
8745 if (!gclass->inst->is_open)
8746 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8747 if (gclass->inst->is_reference)
8748 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8749 gclass->inst->type_argv [i] = t;
8752 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8754 gclass->container_class = klass;
8756 geninst = g_new0 (MonoType, 1);
8757 geninst->type = MONO_TYPE_GENERICINST;
8759 cached = mono_metadata_lookup_generic_class (gclass);
8762 mono_loader_unlock ();
8763 geninst->data.generic_class = cached;
8767 geninst->data.generic_class = gclass;
8769 gclass->context = g_new0 (MonoGenericContext, 1);
8770 gclass->context->container = gclass->container_class->generic_container;
8771 gclass->context->gclass = gclass;
8773 mono_loader_unlock ();
8779 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8782 MonoGenericClass *gclass, *cached;
8783 MonoInflatedGenericClass *igclass;
8787 klass = mono_class_from_mono_type (type);
8788 if (!klass->generic_container && !klass->generic_class &&
8789 !(klass->nested_in && klass->nested_in->generic_container))
8792 mono_loader_lock ();
8794 igclass = g_new0 (MonoInflatedGenericClass, 1);
8795 gclass = &igclass->generic_class;
8796 gclass->is_inflated = TRUE;
8798 gclass->inst = g_new0 (MonoGenericInst, 1);
8799 gclass->inst->type_argc = type_argc;
8800 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8801 gclass->inst->is_reference = 1;
8803 for (i = 0; i < gclass->inst->type_argc; ++i) {
8804 MonoType *t = dup_type (types [i]);
8806 if (!gclass->inst->is_open)
8807 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8808 if (gclass->inst->is_reference)
8809 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8811 gclass->inst->type_argv [i] = t;
8814 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8816 gclass->container_class = klass;
8818 if (klass->generic_class) {
8819 MonoGenericClass *kgclass = klass->generic_class;
8820 MonoGenericClass *ogclass = gclass;
8822 gclass->context = g_new0 (MonoGenericContext, 1);
8823 gclass->context->container = gclass->container_class->generic_container;
8824 gclass->context->gclass = gclass;
8826 igclass = g_new0 (MonoInflatedGenericClass, 1);
8827 gclass = &igclass->generic_class;
8828 gclass->is_inflated = TRUE;
8830 gclass->inst = g_new0 (MonoGenericInst, 1);
8831 gclass->inst->type_argc = kgclass->inst->type_argc;
8832 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8833 gclass->inst->is_reference = 1;
8835 for (i = 0; i < gclass->inst->type_argc; i++) {
8836 MonoType *t = kgclass->inst->type_argv [i];
8838 t = mono_class_inflate_generic_type (t, ogclass->context);
8840 if (!gclass->inst->is_open)
8841 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8842 if (gclass->inst->is_reference)
8843 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8845 gclass->inst->type_argv [i] = t;
8848 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8850 gclass->container_class = kgclass->container_class;
8853 geninst = g_new0 (MonoType, 1);
8854 geninst->type = MONO_TYPE_GENERICINST;
8856 cached = mono_metadata_lookup_generic_class (gclass);
8859 mono_loader_unlock ();
8860 geninst->data.generic_class = cached;
8864 geninst->data.generic_class = gclass;
8866 gclass->context = g_new0 (MonoGenericContext, 1);
8867 gclass->context->container = gclass->container_class->generic_container;
8868 gclass->context->gclass = gclass;
8870 mono_loader_unlock ();
8875 static inline MonoType*
8876 dup_type (const MonoType *original)
8878 MonoType *r = g_new0 (MonoType, 1);
8880 r->attrs = original->attrs;
8881 r->byref = original->byref;
8882 if (original->type == MONO_TYPE_PTR)
8883 r->data.type = dup_type (original->data.type);
8884 else if (original->type == MONO_TYPE_ARRAY)
8885 r->data.array = mono_dup_array_type (original->data.array);
8886 else if (original->type == MONO_TYPE_FNPTR)
8887 r->data.method = mono_metadata_signature_deep_dup (original->data.method);
8888 mono_stats.generics_metadata_size += sizeof (MonoType);
8892 MonoReflectionMethod*
8893 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8895 MonoMethod *method, *inflated;
8896 MonoReflectionMethodBuilder *mb = NULL;
8897 MonoGenericContainer *container;
8898 MonoGenericMethod *gmethod;
8899 MonoGenericContext *context;
8900 MonoGenericInst *ginst;
8903 MONO_ARCH_SAVE_REGS;
8904 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8905 MonoReflectionTypeBuilder *tb;
8908 mb = (MonoReflectionMethodBuilder *) rmethod;
8909 tb = (MonoReflectionTypeBuilder *) mb->type;
8910 klass = mono_class_from_mono_type (tb->type.type);
8912 method = methodbuilder_to_mono_method (klass, mb);
8914 method = rmethod->method;
8917 method = mono_get_inflated_method (method);
8919 count = mono_method_signature (method)->generic_param_count;
8920 if (count != mono_array_length (types))
8923 container = method->generic_container;
8924 g_assert (container);
8926 if (!container->method_hash)
8927 container->method_hash = g_hash_table_new (
8928 (GHashFunc) mono_metadata_generic_method_hash,
8929 (GCompareFunc) mono_metadata_generic_method_equal);
8931 ginst = g_new0 (MonoGenericInst,1 );
8932 ginst->type_argc = count;
8933 ginst->type_argv = g_new0 (MonoType *, count);
8934 ginst->is_reference = 1;
8935 for (i = 0; i < count; i++) {
8936 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8937 ginst->type_argv [i] = dup_type (garg->type);
8939 if (!ginst->is_open)
8940 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8941 if (ginst->is_reference)
8942 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8944 ginst = mono_metadata_lookup_generic_inst (ginst);
8946 gmethod = g_new0 (MonoGenericMethod, 1);
8947 gmethod->generic_class = method->klass->generic_class;
8948 gmethod->container = container;
8949 gmethod->inst = ginst;
8951 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8955 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8958 gmethod->reflection_info = rmethod;
8960 context = g_new0 (MonoGenericContext, 1);
8961 context->container = container;
8962 context->gclass = method->klass->generic_class;
8963 context->gmethod = gmethod;
8965 if (method->is_inflated)
8966 method = ((MonoMethodInflated *) method)->declaring;
8968 inflated = mono_class_inflate_generic_method (method, context);
8969 g_hash_table_insert (container->method_hash, gmethod, inflated);
8971 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8975 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8977 MonoGenericMethod *gmethod = NULL;
8978 MonoInflatedGenericClass *gclass;
8979 MonoGenericContext *context;
8983 klass = mono_class_from_mono_type (type->type.type);
8984 gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
8985 n = mono_method_signature (method)->generic_param_count;
8987 context = gclass->generic_class.context;
8988 g_assert (context && context->container);
8990 gmethod = g_new0 (MonoGenericMethod, 1);
8991 gmethod->generic_class = &gclass->generic_class;
8992 gmethod->container = method->generic_container;
8993 gmethod->reflection_info = obj;
8995 gmethod->inst = g_new0 (MonoGenericInst, 1);
8996 gmethod->inst->type_argc = n;
8997 gmethod->inst->type_argv = g_new0 (MonoType *, n);
8999 for (i = 0; i < n; i++) {
9000 MonoGenericParam *gparam = &method->generic_container->type_params [i];
9001 g_assert (gparam->pklass);
9002 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
9005 g_assert (gmethod->container->parent == context->container);
9007 context = g_new0 (MonoGenericContext, 1);
9008 context->container = gmethod->container;
9009 context->gclass = &gclass->generic_class;
9010 context->gmethod = gmethod;
9013 return mono_class_inflate_generic_method (method, context);
9017 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9022 gklass = mono_class_from_mono_type (type->generic_type->type);
9024 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9025 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9026 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9027 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9028 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9029 method = ((MonoReflectionMethod *) obj)->method;
9031 method = NULL; /* prevent compiler warning */
9032 g_assert_not_reached ();
9035 return inflate_mono_method (type, method, obj);
9039 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9040 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9043 MonoGenericClass *gclass;
9044 MonoDynamicGenericClass *dgclass;
9045 MonoClass *klass, *gklass;
9048 MONO_ARCH_SAVE_REGS;
9050 klass = mono_class_from_mono_type (type->type.type);
9051 gclass = type->type.type->data.generic_class;
9053 g_assert (gclass->is_dynamic);
9054 dgclass = (MonoDynamicGenericClass *) gclass;
9056 if (dgclass->initialized)
9059 gklass = gclass->container_class;
9060 mono_class_init (gklass);
9062 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9063 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9064 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9065 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9066 dgclass->count_events = events ? mono_array_length (events) : 0;
9068 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9069 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9070 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9071 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9072 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9074 for (i = 0; i < dgclass->count_methods; i++) {
9075 MonoObject *obj = mono_array_get (methods, gpointer, i);
9077 dgclass->methods [i] = inflate_method (type, obj);
9080 for (i = 0; i < dgclass->count_ctors; i++) {
9081 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9083 dgclass->ctors [i] = inflate_method (type, obj);
9086 for (i = 0; i < dgclass->count_fields; i++) {
9087 MonoObject *obj = mono_array_get (fields, gpointer, i);
9088 MonoClassField *field;
9089 MonoInflatedField *ifield;
9091 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9092 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9093 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9094 field = ((MonoReflectionField *) obj)->field;
9096 field = NULL; /* prevent compiler warning */
9097 g_assert_not_reached ();
9100 ifield = g_new0 (MonoInflatedField, 1);
9101 ifield->generic_type = field->type;
9102 ifield->reflection_info = obj;
9104 dgclass->fields [i] = *field;
9105 dgclass->fields [i].parent = klass;
9106 dgclass->fields [i].generic_info = ifield;
9107 dgclass->fields [i].type = mono_class_inflate_generic_type (
9108 field->type, dgclass->generic_class.generic_class.context);
9111 for (i = 0; i < dgclass->count_properties; i++) {
9112 MonoObject *obj = mono_array_get (properties, gpointer, i);
9113 MonoProperty *property = &dgclass->properties [i];
9115 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9116 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9118 property->parent = klass;
9119 property->attrs = pb->attrs;
9120 property->name = mono_string_to_utf8 (pb->name);
9122 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9124 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9125 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9126 *property = *((MonoReflectionProperty *) obj)->property;
9129 property->get = inflate_mono_method (type, property->get, NULL);
9131 property->set = inflate_mono_method (type, property->set, NULL);
9133 g_assert_not_reached ();
9136 for (i = 0; i < dgclass->count_events; i++) {
9137 MonoObject *obj = mono_array_get (events, gpointer, i);
9138 MonoEvent *event = &dgclass->events [i];
9140 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9141 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9143 event->parent = klass;
9144 event->attrs = eb->attrs;
9145 event->name = mono_string_to_utf8 (eb->name);
9147 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9148 if (eb->remove_method)
9149 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9150 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9151 *event = *((MonoReflectionEvent *) obj)->event;
9154 event->add = inflate_mono_method (type, event->add, NULL);
9156 event->remove = inflate_mono_method (type, event->remove, NULL);
9158 g_assert_not_reached ();
9161 dgclass->initialized = TRUE;
9165 ensure_runtime_vtable (MonoClass *klass)
9167 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9170 if (!tb || klass->wastypebuilder)
9173 ensure_runtime_vtable (klass->parent);
9175 num = tb->ctors? mono_array_length (tb->ctors): 0;
9176 num += tb->num_methods;
9177 klass->method.count = num;
9178 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9179 num = tb->ctors? mono_array_length (tb->ctors): 0;
9180 for (i = 0; i < num; ++i)
9181 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9182 num = tb->num_methods;
9184 for (i = 0; i < num; ++i)
9185 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9187 if (tb->interfaces) {
9188 klass->interface_count = mono_array_length (tb->interfaces);
9189 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9190 for (i = 0; i < klass->interface_count; ++i) {
9191 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9192 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9196 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9197 for (i = 0; i < klass->method.count; ++i)
9198 klass->methods [i]->slot = i;
9200 mono_class_setup_interface_offsets (klass);
9204 * The generic vtable is needed even if image->run is not set since some
9205 * runtime code like ves_icall_Type_GetMethodsByName depends on
9206 * method->slot being defined.
9210 * tb->methods could not be freed since it is used for determining
9211 * overrides during dynamic vtable construction.
9216 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9218 MonoReflectionTypeBuilder *tb;
9224 g_assert (klass->image->dynamic);
9226 if (!klass->reflection_info)
9229 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9231 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9235 for (i = 0; i < tb->num_methods; ++i) {
9236 MonoReflectionMethodBuilder *mb =
9237 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9238 if (mb->override_method)
9244 *overrides = g_new0 (MonoMethod*, onum * 2);
9247 for (i = 0; i < tb->num_methods; ++i) {
9248 MonoReflectionMethodBuilder *mb =
9249 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9250 if (mb->override_method) {
9251 (*overrides) [onum * 2] =
9252 mb->override_method->method;
9253 (*overrides) [onum * 2 + 1] =
9256 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9257 g_assert (mb->override_method->method);
9258 g_assert (mb->mhandle);
9265 *num_overrides = onum;
9269 typebuilder_setup_fields (MonoClass *klass)
9271 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9272 MonoReflectionFieldBuilder *fb;
9273 MonoClassField *field;
9278 klass->field.count = tb->num_fields;
9279 klass->field.first = 0;
9281 if (!klass->field.count)
9284 klass->fields = g_new0 (MonoClassField, klass->field.count);
9286 for (i = 0; i < klass->field.count; ++i) {
9287 fb = mono_array_get (tb->fields, gpointer, i);
9288 field = &klass->fields [i];
9289 field->name = mono_string_to_utf8 (fb->name);
9291 /* FIXME: handle type modifiers */
9292 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9293 field->type->attrs = fb->attrs;
9295 field->type = fb->type->type;
9297 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9298 field->data = mono_array_addr (fb->rva_data, char, 0);
9299 if (fb->offset != -1)
9300 field->offset = fb->offset;
9301 field->parent = klass;
9303 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9305 if (fb->def_value) {
9306 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9307 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9308 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9309 /* Copy the data from the blob since it might get realloc-ed */
9310 p = assembly->blob.data + idx;
9311 len = mono_metadata_decode_blob_size (p, &p2);
9313 field->data = g_malloc (len);
9314 memcpy ((gpointer)field->data, p, len);
9317 mono_class_layout_fields (klass);
9321 typebuilder_setup_properties (MonoClass *klass)
9323 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9324 MonoReflectionPropertyBuilder *pb;
9327 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9328 klass->property.first = 0;
9330 klass->properties = g_new0 (MonoProperty, klass->property.count);
9331 for (i = 0; i < klass->property.count; ++i) {
9332 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9333 klass->properties [i].parent = klass;
9334 klass->properties [i].attrs = pb->attrs;
9335 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9337 klass->properties [i].get = pb->get_method->mhandle;
9339 klass->properties [i].set = pb->set_method->mhandle;
9341 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9345 MonoReflectionEvent *
9346 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9348 MonoEvent *event = g_new0 (MonoEvent, 1);
9352 klass = my_mono_class_from_mono_type (tb->type.type);
9354 event->parent = klass;
9355 event->attrs = eb->attrs;
9356 event->name = mono_string_to_utf8 (eb->name);
9358 event->add = eb->add_method->mhandle;
9359 if (eb->remove_method)
9360 event->remove = eb->remove_method->mhandle;
9361 if (eb->raise_method)
9362 event->raise = eb->raise_method->mhandle;
9364 if (eb->other_methods) {
9365 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9366 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9367 MonoReflectionMethodBuilder *mb =
9368 mono_array_get (eb->other_methods,
9369 MonoReflectionMethodBuilder*, j);
9370 event->other [j] = mb->mhandle;
9374 return mono_event_get_object (mono_object_domain (tb), klass, event);
9378 typebuilder_setup_events (MonoClass *klass)
9380 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9381 MonoReflectionEventBuilder *eb;
9384 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9385 klass->event.first = 0;
9387 klass->events = g_new0 (MonoEvent, klass->event.count);
9388 for (i = 0; i < klass->event.count; ++i) {
9389 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9390 klass->events [i].parent = klass;
9391 klass->events [i].attrs = eb->attrs;
9392 klass->events [i].name = mono_string_to_utf8 (eb->name);
9394 klass->events [i].add = eb->add_method->mhandle;
9395 if (eb->remove_method)
9396 klass->events [i].remove = eb->remove_method->mhandle;
9397 if (eb->raise_method)
9398 klass->events [i].raise = eb->raise_method->mhandle;
9400 if (eb->other_methods) {
9401 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9402 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9403 MonoReflectionMethodBuilder *mb =
9404 mono_array_get (eb->other_methods,
9405 MonoReflectionMethodBuilder*, j);
9406 klass->events [i].other [j] = mb->mhandle;
9413 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9417 MonoReflectionType* res;
9420 MONO_ARCH_SAVE_REGS;
9422 domain = mono_object_domain (tb);
9423 klass = my_mono_class_from_mono_type (tb->type.type);
9425 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9428 * we need to lock the domain because the lock will be taken inside
9429 * So, we need to keep the locking order correct.
9431 mono_domain_lock (domain);
9432 mono_loader_lock ();
9433 if (klass->wastypebuilder) {
9434 mono_loader_unlock ();
9435 mono_domain_unlock (domain);
9436 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9439 * Fields to set in klass:
9440 * the various flags: delegate/unicode/contextbound etc.
9442 klass->flags = tb->attrs;
9443 klass->has_cctor = 1;
9444 klass->has_finalize = 1;
9447 if (!((MonoDynamicImage*)klass->image)->run) {
9448 if (klass->generic_container) {
9449 /* FIXME: The code below can't handle generic classes */
9450 klass->wastypebuilder = TRUE;
9451 mono_loader_unlock ();
9452 mono_domain_unlock (domain);
9453 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9458 /* enums are done right away */
9459 if (!klass->enumtype)
9460 ensure_runtime_vtable (klass);
9463 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9464 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9465 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9469 /* fields and object layout */
9470 if (klass->parent) {
9471 if (!klass->parent->size_inited)
9472 mono_class_init (klass->parent);
9473 klass->instance_size = klass->parent->instance_size;
9474 klass->sizes.class_size = 0;
9475 klass->min_align = klass->parent->min_align;
9476 /* if the type has no fields we won't call the field_setup
9477 * routine which sets up klass->has_references.
9479 klass->has_references |= klass->parent->has_references;
9481 klass->instance_size = sizeof (MonoObject);
9482 klass->min_align = 1;
9485 /* FIXME: handle packing_size and instance_size */
9486 typebuilder_setup_fields (klass);
9488 typebuilder_setup_properties (klass);
9490 typebuilder_setup_events (klass);
9492 klass->wastypebuilder = TRUE;
9493 mono_loader_unlock ();
9494 mono_domain_unlock (domain);
9496 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9497 g_assert (res != (MonoReflectionType*)tb);
9503 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9505 MonoGenericParam *param;
9508 MONO_ARCH_SAVE_REGS;
9510 param = g_new0 (MonoGenericParam, 1);
9512 if (gparam->mbuilder) {
9513 if (!gparam->mbuilder->generic_container)
9514 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9515 param->owner = gparam->mbuilder->generic_container;
9516 } else if (gparam->tbuilder) {
9517 g_assert (gparam->tbuilder->generic_container);
9518 param->owner = gparam->tbuilder->generic_container;
9521 param->method = NULL;
9522 param->name = mono_string_to_utf8 (gparam->name);
9523 param->num = gparam->index;
9525 image = &gparam->tbuilder->module->dynamic_image->image;
9526 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9528 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9530 gparam->type.type = g_new0 (MonoType, 1);
9531 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9532 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9533 gparam->type.type->data.generic_param = param;
9537 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9539 MonoDynamicImage *assembly = sig->module->dynamic_image;
9540 guint32 na = mono_array_length (sig->arguments);
9541 guint32 buflen, i, size;
9545 MONO_ARCH_SAVE_REGS;
9547 p = buf = g_malloc (size = 50 + na * 50);
9549 mono_metadata_encode_value (0x07, p, &p);
9550 mono_metadata_encode_value (na, p, &p);
9551 for (i = 0; i < na; ++i) {
9552 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9553 encode_reflection_type (assembly, type, p, &p);
9557 g_assert (buflen < size);
9558 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9559 p = mono_array_addr (result, char, 0);
9560 memcpy (p, buf, buflen);
9567 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9569 MonoDynamicImage *assembly = sig->module->dynamic_image;
9570 guint32 na = mono_array_length (sig->arguments);
9571 guint32 buflen, i, size;
9575 MONO_ARCH_SAVE_REGS;
9577 p = buf = g_malloc (size = 10 + na * 10);
9579 mono_metadata_encode_value (0x06, p, &p);
9580 for (i = 0; i < na; ++i) {
9581 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9582 encode_reflection_type (assembly, type, p, &p);
9586 g_assert (buflen < size);
9587 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9588 p = mono_array_addr (result, char, 0);
9589 memcpy (p, buf, buflen);
9596 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9598 ReflectionMethodBuilder rmb;
9599 MonoMethodSignature *sig;
9602 sig = dynamic_method_to_signature (mb);
9604 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9607 * Resolve references.
9610 * Every second entry in the refs array is reserved for storing handle_class,
9611 * which is needed by the ldtoken implementation in the JIT.
9613 rmb.nrefs = mb->nrefs;
9614 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9615 for (i = 0; i < mb->nrefs; i += 2) {
9616 MonoClass *handle_class;
9617 gpointer ref = resolve_object (mb->module->image,
9618 mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9621 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9624 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9625 rmb.refs [i + 1] = handle_class;
9629 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9633 /* ilgen is no longer needed */
9638 * mono_reflection_lookup_dynamic_token:
9640 * Finish the Builder object pointed to by TOKEN and return the corresponding
9641 * runtime structure. HANDLE_CLASS is set to the class required by
9645 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9647 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9650 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9653 return resolve_object (image, obj, handle_class);
9657 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9659 gpointer result = NULL;
9661 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9662 result = mono_string_intern ((MonoString*)obj);
9663 *handle_class = NULL;
9665 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9666 MonoReflectionType *tb = (MonoReflectionType*)obj;
9667 result = mono_class_from_mono_type (tb->type);
9668 *handle_class = mono_defaults.typehandle_class;
9670 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9671 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9672 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9673 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9674 result = ((MonoReflectionMethod*)obj)->method;
9675 *handle_class = mono_defaults.methodhandle_class;
9677 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9678 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9679 result = mb->mhandle;
9681 /* Type is not yet created */
9682 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9684 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9687 * Hopefully this has been filled in by calling CreateType() on the
9691 * TODO: This won't work if the application finishes another
9692 * TypeBuilder instance instead of this one.
9694 result = mb->mhandle;
9696 *handle_class = mono_defaults.methodhandle_class;
9697 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9698 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9700 result = cb->mhandle;
9702 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9704 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9705 result = cb->mhandle;
9707 *handle_class = mono_defaults.methodhandle_class;
9708 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9709 result = ((MonoReflectionField*)obj)->field;
9710 *handle_class = mono_defaults.fieldhandle_class;
9712 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9713 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9714 result = fb->handle;
9717 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9719 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9720 result = fb->handle;
9722 *handle_class = mono_defaults.fieldhandle_class;
9723 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9724 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9727 klass = tb->type.type->data.klass;
9728 if (klass->wastypebuilder) {
9729 /* Already created */
9733 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9734 result = tb->type.type->data.klass;
9737 *handle_class = mono_defaults.typehandle_class;
9738 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9739 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9740 MonoMethodSignature *sig;
9743 if (helper->arguments)
9744 nargs = mono_array_length (helper->arguments);
9748 sig = mono_metadata_signature_alloc (image, nargs);
9749 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9750 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9752 if (helper->call_conv == 0) /* unmanaged */
9753 sig->call_convention = helper->unmanaged_call_conv - 1;
9755 if (helper->call_conv & 0x02)
9756 sig->call_convention = MONO_CALL_VARARG;
9758 sig->call_convention = MONO_CALL_DEFAULT;
9760 sig->param_count = nargs;
9761 /* TODO: Copy type ? */
9762 sig->ret = helper->return_type->type;
9763 for (i = 0; i < nargs; ++i) {
9764 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9765 sig->params [i] = rt->type;
9769 *handle_class = NULL;
9770 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9771 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9772 /* Already created by the managed code */
9773 g_assert (method->mhandle);
9774 result = method->mhandle;
9775 *handle_class = mono_defaults.methodhandle_class;
9777 g_print (obj->vtable->klass->name);
9778 g_assert_not_reached ();
9784 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9785 const static guint32 declsec_flags_map[] = {
9786 0x00000000, /* empty */
9787 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9788 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9789 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9790 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9791 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9792 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9793 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9794 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9795 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9796 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9797 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9798 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9799 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9800 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9801 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9802 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9803 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9804 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9808 * Returns flags that includes all available security action associated to the handle.
9809 * @token: metadata token (either for a class or a method)
9810 * @image: image where resides the metadata.
9813 mono_declsec_get_flags (MonoImage *image, guint32 token)
9815 guint32 index = mono_metadata_declsec_from_index (image, token);
9816 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9821 for (i = index; i < t->rows; i++) {
9822 guint32 cols [MONO_DECL_SECURITY_SIZE];
9824 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9825 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9828 action = cols [MONO_DECL_SECURITY_ACTION];
9829 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9830 result |= declsec_flags_map [action];
9832 g_assert_not_reached ();
9839 * Get the security actions (in the form of flags) associated with the specified method.
9841 * @method: The method for which we want the declarative security flags.
9842 * Return the declarative security flags for the method (only).
9844 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9845 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9848 mono_declsec_flags_from_method (MonoMethod *method)
9850 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9851 /* FIXME: No cache (for the moment) */
9852 guint32 idx = mono_method_get_index (method);
9853 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9854 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9855 return mono_declsec_get_flags (method->klass->image, idx);
9861 * Get the security actions (in the form of flags) associated with the specified class.
9863 * @klass: The class for which we want the declarative security flags.
9864 * Return the declarative security flags for the class.
9866 * Note: We cache the flags inside the MonoClass structure as this will get
9867 * called very often (at least for each method).
9870 mono_declsec_flags_from_class (MonoClass *klass)
9872 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9873 if (!klass->declsec_flags) {
9874 guint32 idx = mono_metadata_token_index (klass->type_token);
9875 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9876 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9877 /* we cache the flags on classes */
9878 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9880 return klass->declsec_flags;
9886 * Get the security actions (in the form of flags) associated with the specified assembly.
9888 * @assembly: The assembly for which we want the declarative security flags.
9889 * Return the declarative security flags for the assembly.
9892 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9894 guint32 idx = 1; /* there is only one assembly */
9895 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9896 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9897 return mono_declsec_get_flags (assembly->image, idx);
9902 * Fill actions for the specific index (which may either be an encoded class token or
9903 * an encoded method token) from the metadata image.
9904 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9907 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9908 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9910 MonoBoolean result = FALSE;
9912 guint32 cols [MONO_DECL_SECURITY_SIZE];
9913 int index = mono_metadata_declsec_from_index (image, token);
9916 t = &image->tables [MONO_TABLE_DECLSECURITY];
9917 for (i = index; i < t->rows; i++) {
9918 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9920 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9923 /* if present only replace (class) permissions with method permissions */
9924 /* if empty accept either class or method permissions */
9925 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9926 if (!actions->demand.blob) {
9927 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9928 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9929 actions->demand.blob = (char*) (blob + 2);
9930 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9933 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9934 if (!actions->noncasdemand.blob) {
9935 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9936 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9937 actions->noncasdemand.blob = (char*) (blob + 2);
9938 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9941 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9942 if (!actions->demandchoice.blob) {
9943 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9944 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9945 actions->demandchoice.blob = (char*) (blob + 2);
9946 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9956 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9957 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9959 guint32 idx = mono_metadata_token_index (klass->type_token);
9960 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9961 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9962 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9966 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9967 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9969 guint32 idx = mono_method_get_index (method);
9970 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9971 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9972 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9976 * Collect all actions (that requires to generate code in mini) assigned for
9977 * the specified method.
9978 * Note: Don't use the content of actions if the function return FALSE.
9981 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9983 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9984 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9985 MonoBoolean result = FALSE;
9988 /* quick exit if no declarative security is present in the metadata */
9989 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9992 /* we want the original as the wrapper is "free" of the security informations */
9993 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
9994 method = mono_marshal_method_from_wrapper (method);
9999 /* First we look for method-level attributes */
10000 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10001 mono_class_init (method->klass);
10002 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10004 result = mono_declsec_get_method_demands_params (method, demands,
10005 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10008 /* Here we use (or create) the class declarative cache to look for demands */
10009 flags = mono_declsec_flags_from_class (method->klass);
10010 if (flags & mask) {
10012 mono_class_init (method->klass);
10013 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10015 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10016 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10019 /* The boolean return value is used as a shortcut in case nothing needs to
10020 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10026 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10028 * Note: Don't use the content of actions if the function return FALSE.
10031 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10033 MonoBoolean result = FALSE;
10036 /* quick exit if no declarative security is present in the metadata */
10037 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10040 /* we want the original as the wrapper is "free" of the security informations */
10041 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10042 method = mono_marshal_method_from_wrapper (method);
10047 /* results are independant - zeroize both */
10048 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10049 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10051 /* First we look for method-level attributes */
10052 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10053 mono_class_init (method->klass);
10055 result = mono_declsec_get_method_demands_params (method, cmethod,
10056 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10059 /* Here we use (or create) the class declarative cache to look for demands */
10060 flags = mono_declsec_flags_from_class (method->klass);
10061 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10062 mono_class_init (method->klass);
10064 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10065 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10072 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10074 * @klass The inherited class - this is the class that provides the security check (attributes)
10076 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10078 * Note: Don't use the content of actions if the function return FALSE.
10081 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10083 MonoBoolean result = FALSE;
10086 /* quick exit if no declarative security is present in the metadata */
10087 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10090 /* Here we use (or create) the class declarative cache to look for demands */
10091 flags = mono_declsec_flags_from_class (klass);
10092 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10093 mono_class_init (klass);
10094 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10096 result |= mono_declsec_get_class_demands_params (klass, demands,
10097 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10104 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10106 * Note: Don't use the content of actions if the function return FALSE.
10109 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10111 /* quick exit if no declarative security is present in the metadata */
10112 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10115 /* we want the original as the wrapper is "free" of the security informations */
10116 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10117 method = mono_marshal_method_from_wrapper (method);
10122 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10123 mono_class_init (method->klass);
10124 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10126 return mono_declsec_get_method_demands_params (method, demands,
10127 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10134 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10136 guint32 cols [MONO_DECL_SECURITY_SIZE];
10140 int index = mono_metadata_declsec_from_index (image, token);
10144 t = &image->tables [MONO_TABLE_DECLSECURITY];
10145 for (i = index; i < t->rows; i++) {
10146 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10148 /* shortcut - index are ordered */
10149 if (token != cols [MONO_DECL_SECURITY_PARENT])
10152 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10153 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10154 entry->blob = (char*) (metadata + 2);
10155 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10164 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10166 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10167 guint32 idx = mono_method_get_index (method);
10168 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10169 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10170 return get_declsec_action (method->klass->image, idx, action, entry);
10176 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10179 guint32 flags = mono_declsec_flags_from_class (klass);
10180 if (declsec_flags_map [action] & flags) {
10181 guint32 idx = mono_metadata_token_index (klass->type_token);
10182 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10183 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10184 return get_declsec_action (klass->image, idx, action, entry);
10190 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10192 guint32 idx = 1; /* there is only one assembly */
10193 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10194 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10196 return get_declsec_action (assembly->image, idx, action, entry);
10200 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10202 MonoObject *res, *exc;
10204 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10205 static MonoMethod *method = NULL;
10207 if (!System_Reflection_Emit_TypeBuilder) {
10208 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10209 g_assert (System_Reflection_Emit_TypeBuilder);
10211 if (method == NULL) {
10212 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10217 * The result of mono_type_get_object () might be a System.MonoType but we
10218 * need a TypeBuilder so use klass->reflection_info.
10220 g_assert (klass->reflection_info);
10221 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10223 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10225 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10229 return *(MonoBoolean*)mono_object_unbox (res);