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_init (MonoDynamicStream *sh)
246 sh->alloc_size = 4096;
247 sh->data = g_malloc (4096);
248 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
249 string_heap_insert (sh, "");
253 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
257 make_room_in_stream (stream, stream->index + len);
258 memcpy (stream->data + stream->index, data, len);
260 stream->index += len;
262 * align index? Not without adding an additional param that controls it since
263 * we may store a blob value in pieces.
269 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
273 make_room_in_stream (stream, stream->index + len);
274 memset (stream->data + stream->index, 0, len);
276 stream->index += len;
281 stream_data_align (MonoDynamicStream *stream)
284 guint32 count = stream->index % 4;
286 /* we assume the stream data will be aligned */
288 mono_image_add_stream_data (stream, buf, 4 - count);
292 mono_blob_entry_hash (const char* str)
296 len = mono_metadata_decode_blob_size (str, &str);
300 for (str += 1; str < end; str++)
301 h = (h << 5) - h + *str;
309 mono_blob_entry_equal (const char *str1, const char *str2) {
313 len = mono_metadata_decode_blob_size (str1, &end1);
314 len2 = mono_metadata_decode_blob_size (str2, &end2);
317 return memcmp (end1, end2, len) == 0;
321 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
325 gpointer oldkey, oldval;
327 copy = g_malloc (s1+s2);
328 memcpy (copy, b1, s1);
329 memcpy (copy + s1, b2, s2);
330 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
332 idx = GPOINTER_TO_UINT (oldval);
334 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
335 mono_image_add_stream_data (&assembly->blob, b2, s2);
336 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
342 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
343 * dest may be misaligned.
346 swap_with_size (char *dest, const char* val, int len, int nelem) {
347 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
350 for (elem = 0; elem < nelem; ++elem) {
376 g_assert_not_reached ();
382 memcpy (dest, val, len * nelem);
387 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
391 guint32 idx = 0, len;
393 len = str->length * 2;
394 mono_metadata_encode_value (len, b, &b);
395 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
397 char *swapped = g_malloc (2 * mono_string_length (str));
398 const char *p = (const char*)mono_string_chars (str);
400 swap_with_size (swapped, p, 2, mono_string_length (str));
401 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
405 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
410 /* modified version needed to handle building corlib */
412 my_mono_class_from_mono_type (MonoType *type) {
413 switch (type->type) {
414 case MONO_TYPE_ARRAY:
416 case MONO_TYPE_SZARRAY:
417 case MONO_TYPE_GENERICINST:
418 return mono_class_from_mono_type (type);
421 g_assert (type->data.generic_param->pklass);
422 return type->data.generic_param->pklass;
424 /* should be always valid when we reach this case... */
425 return type->data.klass;
430 default_class_from_mono_type (MonoType *type)
432 switch (type->type) {
433 case MONO_TYPE_OBJECT:
434 return mono_defaults.object_class;
436 return mono_defaults.void_class;
437 case MONO_TYPE_BOOLEAN:
438 return mono_defaults.boolean_class;
440 return mono_defaults.char_class;
442 return mono_defaults.sbyte_class;
444 return mono_defaults.byte_class;
446 return mono_defaults.int16_class;
448 return mono_defaults.uint16_class;
450 return mono_defaults.int32_class;
452 return mono_defaults.uint32_class;
454 return mono_defaults.int_class;
456 return mono_defaults.uint_class;
458 return mono_defaults.int64_class;
460 return mono_defaults.uint64_class;
462 return mono_defaults.single_class;
464 return mono_defaults.double_class;
465 case MONO_TYPE_STRING:
466 return mono_defaults.string_class;
468 g_warning ("implement me 0x%02x\n", type->type);
469 g_assert_not_reached ();
476 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char *p, char **endbuf)
481 g_assert_not_reached ();
485 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
486 encode_type (assembly, &gclass->container_class->byval_arg, p, &p);
487 mono_metadata_encode_value (gclass->inst->type_argc, p, &p);
488 for (i = 0; i < gclass->inst->type_argc; ++i)
489 encode_type (assembly, gclass->inst->type_argv [i], p, &p);
495 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
498 g_assert_not_reached ();
503 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
507 case MONO_TYPE_BOOLEAN:
521 case MONO_TYPE_STRING:
522 case MONO_TYPE_OBJECT:
523 case MONO_TYPE_TYPEDBYREF:
524 mono_metadata_encode_value (type->type, p, &p);
527 mono_metadata_encode_value (type->type, p, &p);
528 encode_type (assembly, type->data.type, p, &p);
530 case MONO_TYPE_SZARRAY:
531 mono_metadata_encode_value (type->type, p, &p);
532 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
534 case MONO_TYPE_VALUETYPE:
535 case MONO_TYPE_CLASS: {
536 MonoClass *k = mono_class_from_mono_type (type);
538 * Make sure we use the correct type.
540 mono_metadata_encode_value (k->byval_arg.type, p, &p);
542 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
543 * otherwise two typerefs could point to the same type, leading to
544 * verification errors.
546 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
549 case MONO_TYPE_ARRAY:
550 mono_metadata_encode_value (type->type, p, &p);
551 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
552 mono_metadata_encode_value (type->data.array->rank, p, &p);
553 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
554 mono_metadata_encode_value (0, p, &p);
556 case MONO_TYPE_GENERICINST:
557 encode_generic_class (assembly, type->data.generic_class, p, &p);
561 mono_metadata_encode_value (type->type, p, &p);
562 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
565 g_error ("need to encode type %x", type->type);
571 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
574 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
578 encode_type (assembly, type->type, p, endbuf);
582 g_assert_not_reached ();
587 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
592 for (i = 0; i < mono_array_length (modreq); ++i) {
593 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
594 *p = MONO_TYPE_CMOD_REQD;
596 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
600 for (i = 0; i < mono_array_length (modopt); ++i) {
601 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
602 *p = MONO_TYPE_CMOD_OPT;
604 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
611 generic_class_get_signature_size (MonoGenericClass *gclass)
617 g_assert_not_reached ();
620 size += 1 + type_get_signature_size (&gclass->container_class->byval_arg);
622 for (i = 0; i < gclass->inst->type_argc; ++i)
623 size += type_get_signature_size (gclass->inst->type_argv [i]);
629 type_get_signature_size (MonoType *type)
634 g_assert_not_reached ();
642 case MONO_TYPE_BOOLEAN:
656 case MONO_TYPE_STRING:
657 case MONO_TYPE_OBJECT:
658 case MONO_TYPE_TYPEDBYREF:
661 return size + 1 + type_get_signature_size (type->data.type);
662 case MONO_TYPE_SZARRAY:
663 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
664 case MONO_TYPE_VALUETYPE:
665 case MONO_TYPE_CLASS:
667 case MONO_TYPE_ARRAY:
668 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
669 case MONO_TYPE_GENERICINST:
670 return size + generic_class_get_signature_size (type->data.generic_class);
675 g_error ("need to encode type %x", type->type);
681 method_get_signature_size (MonoMethodSignature *sig)
686 size = type_get_signature_size (sig->ret);
687 for (i = 0; i < sig->param_count; i++)
688 size += type_get_signature_size (sig->params [i]);
690 if (sig->generic_param_count)
692 if (sig->sentinelpos >= 0)
699 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
704 guint32 nparams = sig->param_count;
705 guint32 size = 11 + method_get_signature_size (sig);
713 p = buf = g_malloc (size);
715 * FIXME: vararg, explicit_this, differenc call_conv values...
717 *p = sig->call_convention;
719 *p |= 0x20; /* hasthis */
720 if (sig->generic_param_count)
721 *p |= 0x10; /* generic */
723 if (sig->generic_param_count)
724 mono_metadata_encode_value (sig->generic_param_count, p, &p);
725 mono_metadata_encode_value (nparams, p, &p);
726 encode_type (assembly, sig->ret, p, &p);
727 for (i = 0; i < nparams; ++i) {
728 if (i == sig->sentinelpos)
729 *p++ = MONO_TYPE_SENTINEL;
730 encode_type (assembly, sig->params [i], p, &p);
733 g_assert (p - buf < size);
734 mono_metadata_encode_value (p-buf, b, &b);
735 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
741 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
744 * FIXME: reuse code from method_encode_signature().
749 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
750 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
751 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
752 guint32 size = 41 + nparams * 40 + notypes * 40;
757 p = buf = g_malloc (size);
758 /* LAMESPEC: all the call conv spec is foobared */
759 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
760 if (mb->call_conv & 2)
761 *p |= 0x5; /* vararg */
762 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
763 *p |= 0x20; /* hasthis */
765 *p |= 0x10; /* generic */
768 mono_metadata_encode_value (ngparams, p, &p);
769 mono_metadata_encode_value (nparams + notypes, p, &p);
770 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
771 encode_reflection_type (assembly, mb->rtype, p, &p);
772 for (i = 0; i < nparams; ++i) {
773 MonoArray *modreq = NULL;
774 MonoArray *modopt = NULL;
775 MonoReflectionType *pt;
777 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
778 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
779 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
780 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
781 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
782 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
783 encode_reflection_type (assembly, pt, p, &p);
786 *p++ = MONO_TYPE_SENTINEL;
787 for (i = 0; i < notypes; ++i) {
788 MonoReflectionType *pt;
790 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
791 encode_reflection_type (assembly, pt, p, &p);
795 g_assert (p - buf < size);
796 mono_metadata_encode_value (p-buf, b, &b);
797 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
803 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
805 MonoDynamicTable *table;
808 guint32 idx, sig_idx, size;
809 guint nl = mono_array_length (ilgen->locals);
816 p = buf = g_malloc (size);
817 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
818 idx = table->next_idx ++;
820 alloc_table (table, table->rows);
821 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
823 mono_metadata_encode_value (0x07, p, &p);
824 mono_metadata_encode_value (nl, p, &p);
825 for (i = 0; i < nl; ++i) {
826 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
829 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
831 encode_reflection_type (assembly, lb->type, p, &p);
833 g_assert (p - buf < size);
834 mono_metadata_encode_value (p-buf, b, &b);
835 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
838 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
844 method_count_clauses (MonoReflectionILGen *ilgen)
846 guint32 num_clauses = 0;
849 MonoILExceptionInfo *ex_info;
850 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
851 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
852 if (ex_info->handlers)
853 num_clauses += mono_array_length (ex_info->handlers);
861 static MonoExceptionClause*
862 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
864 MonoExceptionClause *clauses;
865 MonoExceptionClause *clause;
866 MonoILExceptionInfo *ex_info;
867 MonoILExceptionBlock *ex_block;
868 guint32 finally_start;
869 int i, j, clause_index;;
871 clauses = g_new0 (MonoExceptionClause, num_clauses);
874 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
875 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
876 finally_start = ex_info->start + ex_info->len;
877 if (!ex_info->handlers)
879 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
880 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
881 clause = &(clauses [clause_index]);
883 clause->flags = ex_block->type;
884 clause->try_offset = ex_info->start;
886 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
887 clause->try_len = finally_start - ex_info->start;
889 clause->try_len = ex_info->len;
890 clause->handler_offset = ex_block->start;
891 clause->handler_len = ex_block->len;
892 if (ex_block->extype) {
893 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
895 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
896 clause->data.filter_offset = ex_block->filter_offset;
898 clause->data.filter_offset = 0;
900 finally_start = ex_block->start + ex_block->len;
910 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
916 gint32 num_locals = 0;
917 gint32 num_exception = 0;
920 char fat_header [12];
923 guint32 local_sig = 0;
924 guint32 header_size = 12;
927 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
928 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
932 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
934 code = mb->ilgen->code;
935 code_size = mb->ilgen->code_len;
936 max_stack = mb->ilgen->max_stack;
937 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
938 if (mb->ilgen->ex_handlers)
939 num_exception = method_count_clauses (mb->ilgen);
943 char *name = mono_string_to_utf8 (mb->name);
944 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
945 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
948 mono_raise_exception (exception);
951 code_size = mono_array_length (code);
952 max_stack = 8; /* we probably need to run a verifier on the code... */
955 stream_data_align (&assembly->code);
957 /* check for exceptions, maxstack, locals */
958 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
960 if (code_size < 64 && !(code_size & 1)) {
961 flags = (code_size << 2) | 0x2;
962 } else if (code_size < 32 && (code_size & 1)) {
963 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
967 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
968 /* add to the fixup todo list */
969 if (mb->ilgen && mb->ilgen->num_token_fixups)
970 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
971 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
972 return assembly->text_rva + idx;
976 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
978 * FIXME: need to set also the header size in fat_flags.
979 * (and more sects and init locals flags)
983 fat_flags |= METHOD_HEADER_MORE_SECTS;
985 fat_flags |= METHOD_HEADER_INIT_LOCALS;
986 fat_header [0] = fat_flags;
987 fat_header [1] = (header_size / 4 ) << 4;
988 short_value = GUINT16_TO_LE (max_stack);
989 memcpy (fat_header + 2, &short_value, 2);
990 int_value = GUINT32_TO_LE (code_size);
991 memcpy (fat_header + 4, &int_value, 4);
992 int_value = GUINT32_TO_LE (local_sig);
993 memcpy (fat_header + 8, &int_value, 4);
994 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
995 /* add to the fixup todo list */
996 if (mb->ilgen && mb->ilgen->num_token_fixups)
997 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
999 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1000 if (num_exception) {
1001 unsigned char sheader [4];
1002 MonoILExceptionInfo * ex_info;
1003 MonoILExceptionBlock * ex_block;
1006 stream_data_align (&assembly->code);
1007 /* always use fat format for now */
1008 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1009 num_exception *= 6 * sizeof (guint32);
1010 num_exception += 4; /* include the size of the header */
1011 sheader [1] = num_exception & 0xff;
1012 sheader [2] = (num_exception >> 8) & 0xff;
1013 sheader [3] = (num_exception >> 16) & 0xff;
1014 mono_image_add_stream_data (&assembly->code, sheader, 4);
1015 /* fat header, so we are already aligned */
1017 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1018 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1019 if (ex_info->handlers) {
1020 int finally_start = ex_info->start + ex_info->len;
1021 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1023 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1025 val = GUINT32_TO_LE (ex_block->type);
1026 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1028 val = GUINT32_TO_LE (ex_info->start);
1029 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1030 /* need fault, too, probably */
1031 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1032 val = GUINT32_TO_LE (finally_start - ex_info->start);
1034 val = GUINT32_TO_LE (ex_info->len);
1035 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1036 /* handler offset */
1037 val = GUINT32_TO_LE (ex_block->start);
1038 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1040 val = GUINT32_TO_LE (ex_block->len);
1041 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1042 finally_start = ex_block->start + ex_block->len;
1043 if (ex_block->extype) {
1044 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1046 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1047 val = ex_block->filter_offset;
1051 val = GUINT32_TO_LE (val);
1052 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1053 /*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",
1054 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);*/
1057 g_error ("No clauses for ex info block %d", i);
1061 return assembly->text_rva + idx;
1065 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1068 MonoDynamicTable *table;
1071 table = &assembly->tables [table_idx];
1073 g_assert (col < table->columns);
1075 values = table->values + table->columns;
1076 for (i = 1; i <= table->rows; ++i) {
1077 if (values [col] == token)
1079 values += table->columns;
1084 static GHashTable *dynamic_custom_attrs = NULL;
1087 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1089 /* FIXME: Need to do more checks */
1090 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1091 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1093 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1100 static MonoCustomAttrInfo*
1101 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1103 int i, index, count, not_visible;
1104 MonoCustomAttrInfo *ainfo;
1105 MonoReflectionCustomAttr *cattr;
1109 /* FIXME: check in assembly the Run flag is set */
1111 count = mono_array_length (cattrs);
1113 /* Skip nonpublic attributes since MS.NET seems to do the same */
1114 /* FIXME: This needs to be done more globally */
1116 for (i = 0; i < count; ++i) {
1117 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1118 if (!custom_attr_visible (image, cattr))
1121 count -= not_visible;
1123 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1125 ainfo->image = image;
1126 ainfo->num_attrs = count;
1128 for (i = 0; i < count; ++i) {
1129 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1130 if (custom_attr_visible (image, cattr)) {
1131 ainfo->attrs [index].ctor = cattr->ctor->method;
1132 /* FIXME: might want to memdup the data here */
1133 ainfo->attrs [index].data = mono_array_addr (cattr->data, char, 0);
1134 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1143 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1145 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1150 if (!dynamic_custom_attrs)
1151 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1153 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1154 ainfo->cached = TRUE;
1158 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1165 * idx is the table index of the object
1166 * type is one of MONO_CUSTOM_ATTR_*
1169 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1171 MonoDynamicTable *table;
1172 MonoReflectionCustomAttr *cattr;
1174 guint32 count, i, token;
1176 char *p = blob_size;
1178 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1181 count = mono_array_length (cattrs);
1182 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1183 table->rows += count;
1184 alloc_table (table, table->rows);
1185 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1186 idx <<= MONO_CUSTOM_ATTR_BITS;
1188 for (i = 0; i < count; ++i) {
1189 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1190 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1191 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1192 type = mono_metadata_token_index (token);
1193 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1194 switch (mono_metadata_token_table (token)) {
1195 case MONO_TABLE_METHOD:
1196 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1198 case MONO_TABLE_MEMBERREF:
1199 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1202 g_warning ("got wrong token in custom attr");
1205 values [MONO_CUSTOM_ATTR_TYPE] = type;
1207 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1208 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1209 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1210 values += MONO_CUSTOM_ATTR_SIZE;
1216 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1218 MonoDynamicTable *table;
1220 guint32 count, i, idx;
1221 MonoReflectionPermissionSet *perm;
1226 count = mono_array_length (permissions);
1227 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1228 table->rows += count;
1229 alloc_table (table, table->rows);
1231 for (i = 0; i < mono_array_length (permissions); ++i) {
1232 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1234 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1236 idx = mono_metadata_token_index (parent_token);
1237 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1238 switch (mono_metadata_token_table (parent_token)) {
1239 case MONO_TABLE_TYPEDEF:
1240 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1242 case MONO_TABLE_METHOD:
1243 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1245 case MONO_TABLE_ASSEMBLY:
1246 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1249 g_assert_not_reached ();
1252 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1253 values [MONO_DECL_SECURITY_PARENT] = idx;
1254 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1261 * Fill in the MethodDef and ParamDef tables for a method.
1262 * This is used for both normal methods and constructors.
1265 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1267 MonoDynamicTable *table;
1272 /* room in this table is already allocated */
1273 table = &assembly->tables [MONO_TABLE_METHOD];
1274 *mb->table_idx = table->next_idx ++;
1275 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1276 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1277 name = mono_string_to_utf8 (mb->name);
1278 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1280 values [MONO_METHOD_FLAGS] = mb->attrs;
1281 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1282 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1283 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1285 table = &assembly->tables [MONO_TABLE_PARAM];
1286 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1288 mono_image_add_decl_security (assembly,
1289 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1292 MonoDynamicTable *mtable;
1295 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1296 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1299 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1300 if (mono_array_get (mb->pinfo, gpointer, i))
1303 table->rows += count;
1304 alloc_table (table, table->rows);
1305 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1306 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1307 MonoReflectionParamBuilder *pb;
1308 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1309 values [MONO_PARAM_FLAGS] = pb->attrs;
1310 values [MONO_PARAM_SEQUENCE] = i;
1311 if (pb->name != NULL) {
1312 name = mono_string_to_utf8 (pb->name);
1313 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1316 values [MONO_PARAM_NAME] = 0;
1318 values += MONO_PARAM_SIZE;
1319 if (pb->marshal_info) {
1321 alloc_table (mtable, mtable->rows);
1322 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1323 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1324 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1326 pb->table_idx = table->next_idx++;
1327 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1328 guint32 field_type = 0;
1329 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1331 alloc_table (mtable, mtable->rows);
1332 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1333 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1334 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1335 mvalues [MONO_CONSTANT_TYPE] = field_type;
1336 mvalues [MONO_CONSTANT_PADDING] = 0;
1344 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1346 rmb->ilgen = mb->ilgen;
1347 rmb->rtype = mb->rtype;
1348 rmb->parameters = mb->parameters;
1349 rmb->generic_params = mb->generic_params;
1350 rmb->generic_container = mb->generic_container;
1351 rmb->opt_types = NULL;
1352 rmb->pinfo = mb->pinfo;
1353 rmb->attrs = mb->attrs;
1354 rmb->iattrs = mb->iattrs;
1355 rmb->call_conv = mb->call_conv;
1356 rmb->code = mb->code;
1357 rmb->type = mb->type;
1358 rmb->name = mb->name;
1359 rmb->table_idx = &mb->table_idx;
1360 rmb->init_locals = mb->init_locals;
1361 rmb->return_modreq = mb->return_modreq;
1362 rmb->return_modopt = mb->return_modopt;
1363 rmb->param_modreq = mb->param_modreq;
1364 rmb->param_modopt = mb->param_modopt;
1365 rmb->permissions = mb->permissions;
1366 rmb->mhandle = mb->mhandle;
1371 rmb->charset = mb->charset;
1372 rmb->extra_flags = mb->extra_flags;
1373 rmb->native_cc = mb->native_cc;
1374 rmb->dllentry = mb->dllentry;
1380 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1382 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1384 rmb->ilgen = mb->ilgen;
1385 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1386 rmb->parameters = mb->parameters;
1387 rmb->generic_params = NULL;
1388 rmb->generic_container = NULL;
1389 rmb->opt_types = NULL;
1390 rmb->pinfo = mb->pinfo;
1391 rmb->attrs = mb->attrs;
1392 rmb->iattrs = mb->iattrs;
1393 rmb->call_conv = mb->call_conv;
1395 rmb->type = mb->type;
1396 rmb->name = mono_string_new (mono_domain_get (), name);
1397 rmb->table_idx = &mb->table_idx;
1398 rmb->init_locals = mb->init_locals;
1399 rmb->return_modreq = NULL;
1400 rmb->return_modopt = NULL;
1401 rmb->param_modreq = mb->param_modreq;
1402 rmb->param_modopt = mb->param_modopt;
1403 rmb->permissions = mb->permissions;
1404 rmb->mhandle = mb->mhandle;
1410 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1412 rmb->ilgen = mb->ilgen;
1413 rmb->rtype = mb->rtype;
1414 rmb->parameters = mb->parameters;
1415 rmb->generic_params = NULL;
1416 rmb->generic_container = NULL;
1417 rmb->opt_types = NULL;
1419 rmb->attrs = mb->attrs;
1421 rmb->call_conv = mb->call_conv;
1424 rmb->name = mb->name;
1425 rmb->table_idx = NULL;
1426 rmb->init_locals = mb->init_locals;
1427 rmb->skip_visibility = mb->skip_visibility;
1428 rmb->return_modreq = NULL;
1429 rmb->return_modopt = NULL;
1430 rmb->param_modreq = NULL;
1431 rmb->param_modopt = NULL;
1432 rmb->permissions = NULL;
1433 rmb->mhandle = mb->mhandle;
1439 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1441 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1442 MonoDynamicTable *table;
1446 if (!mb->override_method)
1449 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1451 alloc_table (table, table->rows);
1452 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1453 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1454 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1456 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1457 switch (mono_metadata_token_table (tok)) {
1458 case MONO_TABLE_MEMBERREF:
1459 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1461 case MONO_TABLE_METHOD:
1462 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1465 g_assert_not_reached ();
1467 values [MONO_METHODIMPL_DECLARATION] = tok;
1471 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1473 MonoDynamicTable *table;
1476 ReflectionMethodBuilder rmb;
1479 reflection_methodbuilder_from_method_builder (&rmb, mb);
1481 mono_image_basic_method (&rmb, assembly);
1482 mb->table_idx = *rmb.table_idx;
1484 if (mb->dll) { /* It's a P/Invoke method */
1486 /* map CharSet values to on-disk values */
1487 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1488 int extra_flags = mb->extra_flags;
1489 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1491 alloc_table (table, table->rows);
1492 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1494 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1495 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1497 name = mono_string_to_utf8 (mb->dllentry);
1499 name = mono_string_to_utf8 (mb->name);
1500 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1502 name = mono_string_to_utf8 (mb->dll);
1503 moduleref = string_heap_insert (&assembly->sheap, name);
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;
1813 /* maybe this fixup should be done in the C# code */
1814 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1815 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1816 table = &assembly->tables [MONO_TABLE_FIELD];
1817 fb->table_idx = table->next_idx ++;
1818 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1819 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1820 name = mono_string_to_utf8 (fb->name);
1821 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1823 values [MONO_FIELD_FLAGS] = fb->attrs;
1824 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1826 if (fb->offset != -1) {
1827 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1829 alloc_table (table, table->rows);
1830 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1831 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1832 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1834 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1835 guint32 field_type = 0;
1836 table = &assembly->tables [MONO_TABLE_CONSTANT];
1838 alloc_table (table, table->rows);
1839 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1840 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1841 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1842 values [MONO_CONSTANT_TYPE] = field_type;
1843 values [MONO_CONSTANT_PADDING] = 0;
1845 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1847 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1849 alloc_table (table, table->rows);
1850 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1851 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1853 * We store it in the code section because it's simpler for now.
1856 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1858 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1859 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1861 if (fb->marshal_info) {
1862 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1864 alloc_table (table, table->rows);
1865 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1866 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1867 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1872 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1876 char *b = blob_size;
1877 guint32 nparams = 0;
1878 MonoReflectionMethodBuilder *mb = fb->get_method;
1879 MonoReflectionMethodBuilder *smb = fb->set_method;
1880 guint32 idx, i, size;
1882 if (mb && mb->parameters)
1883 nparams = mono_array_length (mb->parameters);
1884 if (!mb && smb && smb->parameters)
1885 nparams = mono_array_length (smb->parameters) - 1;
1886 size = 24 + nparams * 10;
1887 buf = p = g_malloc (size);
1890 mono_metadata_encode_value (nparams, p, &p);
1892 encode_reflection_type (assembly, mb->rtype, p, &p);
1893 for (i = 0; i < nparams; ++i) {
1894 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1895 encode_reflection_type (assembly, pt, p, &p);
1898 /* the property type is the last param */
1899 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1900 for (i = 0; i < nparams; ++i) {
1901 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1902 encode_reflection_type (assembly, pt, p, &p);
1906 encode_reflection_type (assembly, fb->type, p, &p);
1910 g_assert (p - buf < size);
1911 mono_metadata_encode_value (p-buf, b, &b);
1912 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1918 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1920 MonoDynamicTable *table;
1923 guint num_methods = 0;
1927 * we need to set things in the following tables:
1928 * PROPERTYMAP (info already filled in _get_type_info ())
1929 * PROPERTY (rows already preallocated in _get_type_info ())
1930 * METHOD (method info already done with the generic method code)
1933 table = &assembly->tables [MONO_TABLE_PROPERTY];
1934 pb->table_idx = table->next_idx ++;
1935 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1936 name = mono_string_to_utf8 (pb->name);
1937 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1939 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1940 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1942 /* FIXME: we still don't handle 'other' methods */
1943 if (pb->get_method) num_methods ++;
1944 if (pb->set_method) num_methods ++;
1946 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1947 table->rows += num_methods;
1948 alloc_table (table, table->rows);
1950 if (pb->get_method) {
1951 semaidx = table->next_idx ++;
1952 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1953 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1954 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1955 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1957 if (pb->set_method) {
1958 semaidx = table->next_idx ++;
1959 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1960 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1961 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1962 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1967 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1969 MonoDynamicTable *table;
1972 guint num_methods = 0;
1976 * we need to set things in the following tables:
1977 * EVENTMAP (info already filled in _get_type_info ())
1978 * EVENT (rows already preallocated in _get_type_info ())
1979 * METHOD (method info already done with the generic method code)
1982 table = &assembly->tables [MONO_TABLE_EVENT];
1983 eb->table_idx = table->next_idx ++;
1984 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1985 name = mono_string_to_utf8 (eb->name);
1986 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1988 values [MONO_EVENT_FLAGS] = eb->attrs;
1989 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1992 * FIXME: we still don't handle 'other' methods
1994 if (eb->add_method) num_methods ++;
1995 if (eb->remove_method) num_methods ++;
1996 if (eb->raise_method) num_methods ++;
1998 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1999 table->rows += num_methods;
2000 alloc_table (table, table->rows);
2002 if (eb->add_method) {
2003 semaidx = table->next_idx ++;
2004 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2005 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2006 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2007 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2009 if (eb->remove_method) {
2010 semaidx = table->next_idx ++;
2011 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2012 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2013 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2014 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2016 if (eb->raise_method) {
2017 semaidx = table->next_idx ++;
2018 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2019 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2020 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2021 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2026 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2028 MonoDynamicTable *table;
2029 guint32 num_constraints, i;
2033 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2034 num_constraints = gparam->iface_constraints ?
2035 mono_array_length (gparam->iface_constraints) : 0;
2036 table->rows += num_constraints;
2037 if (gparam->base_type)
2039 alloc_table (table, table->rows);
2041 if (gparam->base_type) {
2042 table_idx = table->next_idx ++;
2043 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2045 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2046 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2047 assembly, gparam->base_type->type);
2050 for (i = 0; i < num_constraints; i++) {
2051 MonoReflectionType *constraint = mono_array_get (
2052 gparam->iface_constraints, gpointer, i);
2054 table_idx = table->next_idx ++;
2055 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2057 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2058 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2059 assembly, constraint->type);
2064 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2066 GenericParamTableEntry *entry;
2069 * The GenericParam table must be sorted according to the `owner' field.
2070 * We need to do this sorting prior to writing the GenericParamConstraint
2071 * table, since we have to use the final GenericParam table indices there
2072 * and they must also be sorted.
2075 entry = g_new0 (GenericParamTableEntry, 1);
2076 entry->owner = owner;
2077 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2079 g_ptr_array_add (assembly->gen_params, entry);
2083 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2085 MonoDynamicTable *table;
2086 MonoGenericParam *param;
2090 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2091 table_idx = table->next_idx ++;
2092 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2094 param = entry->gparam->type.type->data.generic_param;
2096 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2097 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2098 values [MONO_GENERICPARAM_NUMBER] = param->num;
2099 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2101 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2103 encode_constraints (entry->gparam, table_idx, assembly);
2107 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2109 MonoDynamicTable *table;
2112 guint32 cols [MONO_ASSEMBLY_SIZE];
2116 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2119 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2120 table = &assembly->tables [MONO_TABLE_MODULEREF];
2121 token = table->next_idx ++;
2123 alloc_table (table, table->rows);
2124 values = table->values + token * MONO_MODULEREF_SIZE;
2125 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2127 token <<= MONO_RESOLTION_SCOPE_BITS;
2128 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2129 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2134 if (image->assembly->dynamic)
2136 memset (cols, 0, sizeof (cols));
2138 /* image->assembly->image is the manifest module */
2139 image = image->assembly->image;
2140 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2143 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2144 token = table->next_idx ++;
2146 alloc_table (table, table->rows);
2147 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2148 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2149 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2150 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2151 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2152 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2153 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2154 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2155 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2157 if (strcmp ("", image->assembly->aname.culture)) {
2158 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2159 image->assembly->aname.culture);
2162 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2163 guchar pubtoken [9];
2165 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2166 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2168 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2170 token <<= MONO_RESOLTION_SCOPE_BITS;
2171 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2172 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2177 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2179 MonoDynamicTable *table;
2185 char *b = blob_size;
2187 switch (type->type) {
2188 case MONO_TYPE_FNPTR:
2190 case MONO_TYPE_SZARRAY:
2191 case MONO_TYPE_ARRAY:
2193 case MONO_TYPE_MVAR:
2194 case MONO_TYPE_GENERICINST:
2195 encode_type (assembly, type, p, &p);
2197 case MONO_TYPE_CLASS:
2198 case MONO_TYPE_VALUETYPE: {
2199 MonoClass *k = mono_class_from_mono_type (type);
2200 if (!k || !k->generic_class)
2202 encode_generic_class (assembly, k->generic_class, p, &p);
2209 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2210 if (assembly->save) {
2211 g_assert (p-sig < 128);
2212 mono_metadata_encode_value (p-sig, b, &b);
2213 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2214 alloc_table (table, table->rows + 1);
2215 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2216 values [MONO_TYPESPEC_SIGNATURE] = token;
2219 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2220 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2226 * Despite the name, we handle also TypeSpec (with the above helper).
2229 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2231 MonoDynamicTable *table;
2233 guint32 token, scope, enclosing;
2236 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2239 token = create_typespec (assembly, type);
2242 klass = my_mono_class_from_mono_type (type);
2244 klass = mono_class_from_mono_type (type);
2247 * If it's in the same module and not a generic type parameter:
2249 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2250 (type->type != MONO_TYPE_MVAR)) {
2251 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2252 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2253 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2257 if (klass->nested_in) {
2258 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2259 /* get the typeref idx of the enclosing type */
2260 enclosing >>= MONO_TYPEDEFORREF_BITS;
2261 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2263 scope = resolution_scope_from_image (assembly, klass->image);
2265 table = &assembly->tables [MONO_TABLE_TYPEREF];
2266 if (assembly->save) {
2267 alloc_table (table, table->rows + 1);
2268 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2269 values [MONO_TYPEREF_SCOPE] = scope;
2270 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2271 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2273 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2274 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2276 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2281 * Insert a memberef row into the metadata: the token that point to the memberref
2282 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2283 * mono_image_get_fieldref_token()).
2284 * The sig param is an index to an already built signature.
2287 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2289 MonoDynamicTable *table;
2291 guint32 token, pclass;
2294 parent = mono_image_typedef_or_ref (assembly, type);
2295 switch (parent & MONO_TYPEDEFORREF_MASK) {
2296 case MONO_TYPEDEFORREF_TYPEREF:
2297 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2299 case MONO_TYPEDEFORREF_TYPESPEC:
2300 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2302 case MONO_TYPEDEFORREF_TYPEDEF:
2303 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2306 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2309 /* extract the index */
2310 parent >>= MONO_TYPEDEFORREF_BITS;
2312 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2314 if (assembly->save) {
2315 alloc_table (table, table->rows + 1);
2316 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2317 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2318 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2319 values [MONO_MEMBERREF_SIGNATURE] = sig;
2322 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2329 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2332 MonoMethodSignature *sig;
2334 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2339 * A methodref signature can't contain an unmanaged calling convention.
2341 sig = mono_metadata_signature_dup (mono_method_signature (method));
2342 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2343 sig->call_convention = MONO_CALL_DEFAULT;
2344 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2345 method->name, method_encode_signature (assembly, sig));
2347 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2352 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2353 const gchar *name, guint32 sig)
2355 MonoDynamicTable *table;
2359 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2361 if (assembly->save) {
2362 alloc_table (table, table->rows + 1);
2363 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2364 values [MONO_MEMBERREF_CLASS] = original;
2365 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2366 values [MONO_MEMBERREF_SIGNATURE] = sig;
2369 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2376 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2379 ReflectionMethodBuilder rmb;
2381 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2385 reflection_methodbuilder_from_method_builder (&rmb, mb);
2387 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2388 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2389 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2394 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2397 ReflectionMethodBuilder rmb;
2399 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2403 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2405 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2406 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2407 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2412 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2417 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2420 g_assert (f->field->parent);
2421 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2422 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2423 f->field->name, fieldref_encode_signature (assembly, type));
2424 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2429 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2434 guint32 nparams = gmethod->inst->type_argc;
2435 guint32 size = 10 + nparams * 30;
2438 char *b = blob_size;
2440 if (!assembly->save)
2443 p = buf = g_malloc (size);
2445 * FIXME: vararg, explicit_this, differenc call_conv values...
2447 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2448 mono_metadata_encode_value (nparams, p, &p);
2450 for (i = 0; i < nparams; i++)
2451 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2454 g_assert (p - buf < size);
2455 mono_metadata_encode_value (p-buf, b, &b);
2456 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2462 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2464 MonoDynamicTable *table;
2466 guint32 token, mtoken = 0, sig;
2467 MonoMethodInflated *imethod;
2468 MonoMethod *declaring;
2470 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2472 g_assert (method->is_inflated);
2473 method = mono_get_inflated_method (method);
2474 imethod = (MonoMethodInflated *) method;
2475 declaring = imethod->declaring;
2477 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2478 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2480 if (!mono_method_signature (declaring)->generic_param_count)
2483 switch (mono_metadata_token_table (mtoken)) {
2484 case MONO_TABLE_MEMBERREF:
2485 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2487 case MONO_TABLE_METHOD:
2488 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2491 g_assert_not_reached ();
2494 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2496 if (assembly->save) {
2497 alloc_table (table, table->rows + 1);
2498 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2499 values [MONO_METHODSPEC_METHOD] = mtoken;
2500 values [MONO_METHODSPEC_SIGNATURE] = sig;
2503 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2510 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2512 MonoMethodInflated *imethod;
2513 MonoMethod *inflated;
2516 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2520 g_assert (method->is_inflated);
2521 inflated = mono_get_inflated_method (method);
2522 imethod = (MonoMethodInflated *) inflated;
2524 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2525 token = method_encode_methodspec (assembly, inflated);
2527 guint32 sig = method_encode_signature (
2528 assembly, mono_method_signature (imethod->declaring));
2529 token = mono_image_get_memberref_token (
2530 assembly, &inflated->klass->byval_arg, inflated->name, sig);
2533 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2538 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2540 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2543 m = mono_get_inflated_method (m);
2545 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2546 token = mono_image_get_memberref_token (
2547 assembly, &m->klass->byval_arg, m->name, sig);
2553 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2555 MonoDynamicTable *table;
2562 char *b = blob_size;
2566 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2567 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2568 * Because of this, we must not insert it into the `typeref' hash table.
2571 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2575 g_assert (tb->generic_params);
2576 klass = mono_class_from_mono_type (tb->type.type);
2578 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2579 encode_type (assembly, &klass->byval_arg, p, &p);
2581 count = mono_array_length (tb->generic_params);
2582 mono_metadata_encode_value (count, p, &p);
2583 for (i = 0; i < count; i++) {
2584 MonoReflectionGenericParam *gparam;
2586 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2588 encode_type (assembly, gparam->type.type, p, &p);
2591 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2592 g_assert (p-sig < 128);
2594 if (assembly->save) {
2595 mono_metadata_encode_value (p-sig, b, &b);
2596 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2597 alloc_table (table, table->rows + 1);
2598 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2599 values [MONO_TYPESPEC_SIGNATURE] = token;
2602 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2603 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2609 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2611 MonoDynamicTable *table;
2614 guint32 token, pclass, parent, sig;
2617 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2621 klass = mono_class_from_mono_type (fb->typeb->type);
2622 name = mono_string_to_utf8 (fb->name);
2624 sig = fieldref_encode_signature (assembly, fb->type->type);
2626 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2627 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2629 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2630 parent >>= MONO_TYPEDEFORREF_BITS;
2632 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2634 if (assembly->save) {
2635 alloc_table (table, table->rows + 1);
2636 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2637 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2638 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2639 values [MONO_MEMBERREF_SIGNATURE] = sig;
2642 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2644 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2649 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2657 char *b = blob_size;
2659 if (!assembly->save)
2663 g_assert (helper->type == 2);
2665 if (helper->arguments)
2666 nargs = mono_array_length (helper->arguments);
2670 size = 10 + (nargs * 10);
2672 p = buf = g_malloc (size);
2674 /* Encode calling convention */
2675 /* Change Any to Standard */
2676 if ((helper->call_conv & 0x03) == 0x03)
2677 helper->call_conv = 0x01;
2678 /* explicit_this implies has_this */
2679 if (helper->call_conv & 0x40)
2680 helper->call_conv &= 0x20;
2682 if (helper->call_conv == 0) { /* Unmanaged */
2683 *p = helper->unmanaged_call_conv - 1;
2686 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2687 if (helper->call_conv & 0x02) /* varargs */
2692 mono_metadata_encode_value (nargs, p, &p);
2693 encode_reflection_type (assembly, helper->return_type, p, &p);
2694 for (i = 0; i < nargs; ++i) {
2695 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2696 encode_reflection_type (assembly, pt, p, &p);
2699 g_assert (p - buf < size);
2700 mono_metadata_encode_value (p-buf, b, &b);
2701 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2708 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2711 MonoDynamicTable *table;
2714 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2715 idx = table->next_idx ++;
2717 alloc_table (table, table->rows);
2718 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2720 values [MONO_STAND_ALONE_SIGNATURE] =
2721 mono_reflection_encode_sighelper (assembly, helper);
2727 reflection_cc_to_file (int call_conv) {
2728 switch (call_conv & 0x3) {
2730 case 1: return MONO_CALL_DEFAULT;
2731 case 2: return MONO_CALL_VARARG;
2733 g_assert_not_reached ();
2740 MonoMethodSignature *sig;
2746 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2751 MonoMethodSignature *sig;
2754 name = mono_string_to_utf8 (m->name);
2755 nparams = mono_array_length (m->parameters);
2756 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2758 sig->sentinelpos = -1;
2759 sig->call_convention = reflection_cc_to_file (m->call_conv);
2760 sig->param_count = nparams;
2761 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2762 for (i = 0; i < nparams; ++i) {
2763 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2764 sig->params [i] = t->type;
2767 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2769 if (strcmp (name, am->name) == 0 &&
2770 mono_metadata_type_equal (am->parent, m->parent->type) &&
2771 mono_metadata_signature_equal (am->sig, sig)) {
2774 m->table_idx = am->token & 0xffffff;
2778 am = g_new0 (ArrayMethod, 1);
2781 am->parent = m->parent->type;
2782 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2783 method_encode_signature (assembly, sig));
2784 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2785 m->table_idx = am->token & 0xffffff;
2790 * Insert into the metadata tables all the info about the TypeBuilder tb.
2791 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2794 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2796 MonoDynamicTable *table;
2798 int i, is_object = 0, is_system = 0;
2801 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2802 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2803 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2804 n = mono_string_to_utf8 (tb->name);
2805 if (strcmp (n, "Object") == 0)
2807 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2809 n = mono_string_to_utf8 (tb->nspace);
2810 if (strcmp (n, "System") == 0)
2812 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2814 if (tb->parent && !(is_system && is_object) &&
2815 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2816 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2818 values [MONO_TYPEDEF_EXTENDS] = 0;
2820 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2821 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2824 * if we have explicitlayout or sequentiallayouts, output data in the
2825 * ClassLayout table.
2827 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2828 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2829 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2831 alloc_table (table, table->rows);
2832 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2833 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2834 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2835 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2838 /* handle interfaces */
2839 if (tb->interfaces) {
2840 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2842 table->rows += mono_array_length (tb->interfaces);
2843 alloc_table (table, table->rows);
2844 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2845 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2846 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2847 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2848 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2849 values += MONO_INTERFACEIMPL_SIZE;
2855 table = &assembly->tables [MONO_TABLE_FIELD];
2856 table->rows += tb->num_fields;
2857 alloc_table (table, table->rows);
2858 for (i = 0; i < tb->num_fields; ++i)
2859 mono_image_get_field_info (
2860 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2863 /* handle constructors */
2865 table = &assembly->tables [MONO_TABLE_METHOD];
2866 table->rows += mono_array_length (tb->ctors);
2867 alloc_table (table, table->rows);
2868 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2869 mono_image_get_ctor_info (domain,
2870 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2873 /* handle methods */
2875 table = &assembly->tables [MONO_TABLE_METHOD];
2876 table->rows += tb->num_methods;
2877 alloc_table (table, table->rows);
2878 for (i = 0; i < tb->num_methods; ++i)
2879 mono_image_get_method_info (
2880 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2883 /* Do the same with properties etc.. */
2884 if (tb->events && mono_array_length (tb->events)) {
2885 table = &assembly->tables [MONO_TABLE_EVENT];
2886 table->rows += mono_array_length (tb->events);
2887 alloc_table (table, table->rows);
2888 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2890 alloc_table (table, table->rows);
2891 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2892 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2893 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2894 for (i = 0; i < mono_array_length (tb->events); ++i)
2895 mono_image_get_event_info (
2896 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2898 if (tb->properties && mono_array_length (tb->properties)) {
2899 table = &assembly->tables [MONO_TABLE_PROPERTY];
2900 table->rows += mono_array_length (tb->properties);
2901 alloc_table (table, table->rows);
2902 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2904 alloc_table (table, table->rows);
2905 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2906 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2907 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2908 for (i = 0; i < mono_array_length (tb->properties); ++i)
2909 mono_image_get_property_info (
2910 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2913 /* handle generic parameters */
2914 if (tb->generic_params) {
2915 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2916 table->rows += mono_array_length (tb->generic_params);
2917 alloc_table (table, table->rows);
2918 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2919 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2921 mono_image_get_generic_param_info (
2922 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2926 mono_image_add_decl_security (assembly,
2927 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2930 MonoDynamicTable *ntable;
2932 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2933 ntable->rows += mono_array_length (tb->subtypes);
2934 alloc_table (ntable, ntable->rows);
2935 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2937 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2938 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2940 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2941 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2942 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2943 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2944 mono_string_to_utf8 (tb->name), tb->table_idx,
2945 ntable->next_idx, ntable->rows);*/
2946 values += MONO_NESTED_CLASS_SIZE;
2953 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2957 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2959 if (!type->subtypes)
2962 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2963 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2964 collect_types (types, subtype);
2969 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2971 if ((*type1)->table_idx < (*type2)->table_idx)
2974 if ((*type1)->table_idx > (*type2)->table_idx)
2981 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2986 for (i = 0; i < mono_array_length (pinfo); ++i) {
2987 MonoReflectionParamBuilder *pb;
2988 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2991 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2996 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2999 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3001 for (i = 0; i < tb->num_fields; ++i) {
3002 MonoReflectionFieldBuilder* fb;
3003 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3004 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3008 for (i = 0; i < mono_array_length (tb->events); ++i) {
3009 MonoReflectionEventBuilder* eb;
3010 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3011 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3014 if (tb->properties) {
3015 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3016 MonoReflectionPropertyBuilder* pb;
3017 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3018 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3022 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3023 MonoReflectionCtorBuilder* cb;
3024 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3025 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3026 params_add_cattrs (assembly, cb->pinfo);
3031 for (i = 0; i < tb->num_methods; ++i) {
3032 MonoReflectionMethodBuilder* mb;
3033 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3034 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3035 params_add_cattrs (assembly, mb->pinfo);
3040 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3041 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3046 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3050 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3052 if (moduleb->global_methods) {
3053 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3054 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3055 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3056 params_add_cattrs (assembly, mb->pinfo);
3060 if (moduleb->global_fields) {
3061 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3062 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3063 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3067 if (moduleb->types) {
3068 for (i = 0; i < moduleb->num_types; ++i)
3069 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3074 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3076 MonoDynamicTable *table;
3080 char *b = blob_size;
3083 table = &assembly->tables [MONO_TABLE_FILE];
3085 alloc_table (table, table->rows);
3086 values = table->values + table->next_idx * MONO_FILE_SIZE;
3087 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3088 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3089 if (module->image->dynamic) {
3090 /* This depends on the fact that the main module is emitted last */
3091 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3092 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3095 path = g_strdup (module->image->name);
3097 mono_sha1_get_digest_from_file (path, hash);
3100 mono_metadata_encode_value (20, b, &b);
3101 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3102 mono_image_add_stream_data (&assembly->blob, hash, 20);
3107 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3109 MonoDynamicTable *table;
3113 table = &assembly->tables [MONO_TABLE_MODULE];
3114 mb->table_idx = table->next_idx ++;
3115 name = mono_string_to_utf8 (mb->module.name);
3116 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3118 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3121 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3122 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3123 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3124 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3128 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3129 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3131 MonoDynamicTable *table;
3135 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3136 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3139 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3141 alloc_table (table, table->rows);
3142 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3144 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3145 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3146 if (klass->nested_in)
3147 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3149 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3150 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3151 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3153 res = table->next_idx;
3157 /* Emit nested types */
3158 if (klass->nested_classes) {
3161 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3162 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3169 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3170 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3175 klass = mono_class_from_mono_type (tb->type.type);
3177 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3179 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3180 parent_index, assembly);
3184 * We need to do this ourselves since klass->nested_classes is not set up.
3187 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3188 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3193 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3194 guint32 module_index, MonoDynamicImage *assembly)
3196 MonoImage *image = module->image;
3200 t = &image->tables [MONO_TABLE_TYPEDEF];
3202 for (i = 0; i < t->rows; ++i) {
3203 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3205 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3206 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3211 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3213 MonoDynamicTable *table;
3219 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3221 if (assemblyb->type_forwarders) {
3222 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3223 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3229 klass = mono_class_from_mono_type (t->type);
3231 scope = resolution_scope_from_image (assembly, klass->image);
3232 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3233 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3236 alloc_table (table, table->rows);
3237 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3239 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3240 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3241 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3242 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3243 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3248 #define align_pointer(base,p)\
3250 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3252 (p) += 4 - (__diff & 3);\
3256 compare_constants (const void *a, const void *b)
3258 const guint32 *a_values = a;
3259 const guint32 *b_values = b;
3260 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3264 compare_semantics (const void *a, const void *b)
3266 const guint32 *a_values = a;
3267 const guint32 *b_values = b;
3268 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3271 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3275 compare_custom_attrs (const void *a, const void *b)
3277 const guint32 *a_values = a;
3278 const guint32 *b_values = b;
3280 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3284 compare_field_marshal (const void *a, const void *b)
3286 const guint32 *a_values = a;
3287 const guint32 *b_values = b;
3289 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3293 compare_nested (const void *a, const void *b)
3295 const guint32 *a_values = a;
3296 const guint32 *b_values = b;
3298 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3302 compare_genericparam (const void *a, const void *b)
3304 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3305 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3307 if ((*b_entry)->owner == (*a_entry)->owner)
3309 (*a_entry)->gparam->type.type->data.generic_param->num -
3310 (*b_entry)->gparam->type.type->data.generic_param->num;
3312 return (*a_entry)->owner - (*b_entry)->owner;
3316 compare_declsecurity_attrs (const void *a, const void *b)
3318 const guint32 *a_values = a;
3319 const guint32 *b_values = b;
3321 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3325 pad_heap (MonoDynamicStream *sh)
3327 if (sh->index & 3) {
3328 int sz = 4 - (sh->index & 3);
3329 memset (sh->data + sh->index, 0, sz);
3336 MonoDynamicStream *stream;
3340 * build_compressed_metadata() fills in the blob of data that represents the
3341 * raw metadata as it will be saved in the PE file. The five streams are output
3342 * and the metadata tables are comnpressed from the guint32 array representation,
3343 * to the compressed on-disk format.
3346 build_compressed_metadata (MonoDynamicImage *assembly)
3348 MonoDynamicTable *table;
3350 guint64 valid_mask = 0;
3351 guint64 sorted_mask;
3352 guint32 heapt_size = 0;
3353 guint32 meta_size = 256; /* allow for header and other stuff */
3354 guint32 table_offset;
3355 guint32 ntables = 0;
3361 struct StreamDesc stream_desc [5];
3363 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3364 for (i = 0; i < assembly->gen_params->len; i++){
3365 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3366 write_generic_param_entry (assembly, entry);
3369 stream_desc [0].name = "#~";
3370 stream_desc [0].stream = &assembly->tstream;
3371 stream_desc [1].name = "#Strings";
3372 stream_desc [1].stream = &assembly->sheap;
3373 stream_desc [2].name = "#US";
3374 stream_desc [2].stream = &assembly->us;
3375 stream_desc [3].name = "#Blob";
3376 stream_desc [3].stream = &assembly->blob;
3377 stream_desc [4].name = "#GUID";
3378 stream_desc [4].stream = &assembly->guid;
3380 /* tables that are sorted */
3381 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3382 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3383 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3384 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3385 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3386 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3388 /* Compute table sizes */
3389 /* the MonoImage has already been created in mono_image_basic_init() */
3390 meta = &assembly->image;
3392 /* sizes should be multiple of 4 */
3393 pad_heap (&assembly->blob);
3394 pad_heap (&assembly->guid);
3395 pad_heap (&assembly->sheap);
3396 pad_heap (&assembly->us);
3398 /* Setup the info used by compute_sizes () */
3399 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3400 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3401 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3403 meta_size += assembly->blob.index;
3404 meta_size += assembly->guid.index;
3405 meta_size += assembly->sheap.index;
3406 meta_size += assembly->us.index;
3408 for (i=0; i < MONO_TABLE_NUM; ++i)
3409 meta->tables [i].rows = assembly->tables [i].rows;
3411 for (i = 0; i < MONO_TABLE_NUM; i++){
3412 if (meta->tables [i].rows == 0)
3414 valid_mask |= (guint64)1 << i;
3416 meta->tables [i].row_size = mono_metadata_compute_size (
3417 meta, i, &meta->tables [i].size_bitfield);
3418 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3420 heapt_size += 24; /* #~ header size */
3421 heapt_size += ntables * 4;
3422 /* make multiple of 4 */
3425 meta_size += heapt_size;
3426 meta->raw_metadata = g_malloc0 (meta_size);
3427 p = meta->raw_metadata;
3428 /* the metadata signature */
3429 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3430 /* version numbers and 4 bytes reserved */
3431 int16val = (guint16*)p;
3432 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3433 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3435 /* version string */
3436 int32val = (guint32*)p;
3437 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3439 memcpy (p, meta->version, strlen (meta->version));
3440 p += GUINT32_FROM_LE (*int32val);
3441 align_pointer (meta->raw_metadata, p);
3442 int16val = (guint16*)p;
3443 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3444 *int16val = GUINT16_TO_LE (5); /* number of streams */
3448 * write the stream info.
3450 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3451 table_offset += 3; table_offset &= ~3;
3453 assembly->tstream.index = heapt_size;
3454 for (i = 0; i < 5; ++i) {
3455 int32val = (guint32*)p;
3456 stream_desc [i].stream->offset = table_offset;
3457 *int32val++ = GUINT32_TO_LE (table_offset);
3458 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3459 table_offset += GUINT32_FROM_LE (*int32val);
3460 table_offset += 3; table_offset &= ~3;
3462 strcpy (p, stream_desc [i].name);
3463 p += strlen (stream_desc [i].name) + 1;
3464 align_pointer (meta->raw_metadata, p);
3467 * now copy the data, the table stream header and contents goes first.
3469 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3470 p = meta->raw_metadata + assembly->tstream.offset;
3471 int32val = (guint32*)p;
3472 *int32val = GUINT32_TO_LE (0); /* reserved */
3475 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3476 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3477 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3478 *p++ = 2; /* version */
3481 *p++ = 1; /* version */
3485 if (meta->idx_string_wide)
3487 if (meta->idx_guid_wide)
3489 if (meta->idx_blob_wide)
3492 *p++ = 1; /* reserved */
3493 int64val = (guint64*)p;
3494 *int64val++ = GUINT64_TO_LE (valid_mask);
3495 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3497 int32val = (guint32*)p;
3498 for (i = 0; i < MONO_TABLE_NUM; i++){
3499 if (meta->tables [i].rows == 0)
3501 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3503 p = (unsigned char*)int32val;
3505 /* sort the tables that still need sorting */
3506 table = &assembly->tables [MONO_TABLE_CONSTANT];
3508 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3509 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3511 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3512 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3514 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3515 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3517 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3518 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3520 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3521 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3522 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3524 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3526 /* compress the tables */
3527 for (i = 0; i < MONO_TABLE_NUM; i++){
3530 guint32 bitfield = meta->tables [i].size_bitfield;
3531 if (!meta->tables [i].rows)
3533 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3534 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3535 meta->tables [i].base = p;
3536 for (row = 1; row <= meta->tables [i].rows; ++row) {
3537 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3538 for (col = 0; col < assembly->tables [i].columns; ++col) {
3539 switch (mono_metadata_table_size (bitfield, col)) {
3541 *p++ = values [col];
3544 *p++ = values [col] & 0xff;
3545 *p++ = (values [col] >> 8) & 0xff;
3548 *p++ = values [col] & 0xff;
3549 *p++ = (values [col] >> 8) & 0xff;
3550 *p++ = (values [col] >> 16) & 0xff;
3551 *p++ = (values [col] >> 24) & 0xff;
3554 g_assert_not_reached ();
3558 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3561 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3562 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3563 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3564 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3565 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3567 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3571 * Some tables in metadata need to be sorted according to some criteria, but
3572 * when methods and fields are first created with reflection, they may be assigned a token
3573 * that doesn't correspond to the final token they will get assigned after the sorting.
3574 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3575 * with the reflection objects that represent them. Once all the tables are set up, the
3576 * reflection objects will contains the correct table index. fixup_method() will fixup the
3577 * tokens for the method with ILGenerator @ilgen.
3580 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3581 guint32 code_idx = GPOINTER_TO_UINT (value);
3582 MonoReflectionILTokenInfo *iltoken;
3583 MonoReflectionFieldBuilder *field;
3584 MonoReflectionCtorBuilder *ctor;
3585 MonoReflectionMethodBuilder *method;
3586 MonoReflectionTypeBuilder *tb;
3587 MonoReflectionArrayMethod *am;
3589 unsigned char *target;
3591 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3592 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3593 target = assembly->code.data + code_idx + iltoken->code_pos;
3594 switch (target [3]) {
3595 case MONO_TABLE_FIELD:
3596 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3597 field = (MonoReflectionFieldBuilder *)iltoken->member;
3598 idx = field->table_idx;
3599 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3600 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3601 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3603 g_assert_not_reached ();
3606 case MONO_TABLE_METHOD:
3607 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3608 method = (MonoReflectionMethodBuilder *)iltoken->member;
3609 idx = method->table_idx;
3610 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3611 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3612 idx = ctor->table_idx;
3613 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3614 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3615 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3616 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3618 g_assert_not_reached ();
3621 case MONO_TABLE_TYPEDEF:
3622 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3623 g_assert_not_reached ();
3624 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3625 idx = tb->table_idx;
3627 case MONO_TABLE_MEMBERREF:
3628 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3629 am = (MonoReflectionArrayMethod*)iltoken->member;
3630 idx = am->table_idx;
3631 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3632 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3633 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3634 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3635 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3636 g_assert (m->klass->generic_class || m->klass->generic_container);
3638 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3640 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3641 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3642 g_assert (f->generic_info);
3644 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3647 g_assert_not_reached ();
3650 case MONO_TABLE_METHODSPEC:
3651 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3652 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3653 g_assert (mono_method_signature (m)->generic_param_count);
3656 g_assert_not_reached ();
3660 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3662 target [0] = idx & 0xff;
3663 target [1] = (idx >> 8) & 0xff;
3664 target [2] = (idx >> 16) & 0xff;
3671 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3672 * value is not known when the table is emitted.
3675 fixup_cattrs (MonoDynamicImage *assembly)
3677 MonoDynamicTable *table;
3679 guint32 type, i, idx, token;
3682 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3684 for (i = 0; i < table->rows; ++i) {
3685 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3687 type = values [MONO_CUSTOM_ATTR_TYPE];
3688 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3689 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3690 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3691 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3694 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3695 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3696 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3697 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3704 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3706 MonoDynamicTable *table;
3710 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3712 alloc_table (table, table->rows);
3713 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3714 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3715 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3716 name = mono_string_to_utf8 (rsrc->name);
3717 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3719 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3724 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3726 MonoDynamicTable *table;
3730 char *b = blob_size;
3732 guint32 idx, offset;
3734 if (rsrc->filename) {
3735 name = mono_string_to_utf8 (rsrc->filename);
3736 sname = g_path_get_basename (name);
3738 table = &assembly->tables [MONO_TABLE_FILE];
3740 alloc_table (table, table->rows);
3741 values = table->values + table->next_idx * MONO_FILE_SIZE;
3742 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3743 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3746 mono_sha1_get_digest_from_file (name, hash);
3747 mono_metadata_encode_value (20, b, &b);
3748 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3749 mono_image_add_stream_data (&assembly->blob, hash, 20);
3751 idx = table->next_idx++;
3753 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3756 offset = mono_array_length (rsrc->data);
3757 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3758 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3759 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3760 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3764 * The entry should be emitted into the MANIFESTRESOURCE table of
3765 * the main module, but that needs to reference the FILE table
3766 * which isn't emitted yet.
3773 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3777 set_version_from_string (MonoString *version, guint32 *values)
3779 gchar *ver, *p, *str;
3782 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3783 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3784 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3785 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3788 ver = str = mono_string_to_utf8 (version);
3789 for (i = 0; i < 4; ++i) {
3790 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3796 /* handle Revision and Build */
3806 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3810 char *b = blob_size;
3815 len = mono_array_length (pkey);
3816 mono_metadata_encode_value (len, b, &b);
3817 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3818 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3820 /* Special case: check for ECMA key (16 bytes) */
3821 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, guint8, 0), len)) {
3822 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3823 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3824 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3825 /* minimum key size (in 2.0) is 384 bits */
3826 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3828 /* FIXME - verifier */
3829 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3830 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3832 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3838 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3840 MonoDynamicTable *table;
3841 MonoDynamicImage *assembly;
3842 MonoReflectionAssemblyBuilder *assemblyb;
3847 guint32 module_index;
3849 assemblyb = moduleb->assemblyb;
3850 assembly = moduleb->dynamic_image;
3851 domain = mono_object_domain (assemblyb);
3853 /* Emit ASSEMBLY table */
3854 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3855 alloc_table (table, 1);
3856 values = table->values + MONO_ASSEMBLY_SIZE;
3857 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3858 name = mono_string_to_utf8 (assemblyb->name);
3859 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3861 if (assemblyb->culture) {
3862 name = mono_string_to_utf8 (assemblyb->culture);
3863 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3866 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3868 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3869 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3870 set_version_from_string (assemblyb->version, values);
3872 /* Emit FILE + EXPORTED_TYPE table */
3874 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3876 MonoReflectionModuleBuilder *file_module =
3877 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3878 if (file_module != moduleb) {
3879 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3881 if (file_module->types) {
3882 for (j = 0; j < file_module->num_types; ++j) {
3883 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3884 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3889 if (assemblyb->loaded_modules) {
3890 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3891 MonoReflectionModule *file_module =
3892 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3893 mono_image_fill_file_table (domain, file_module, assembly);
3895 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3898 if (assemblyb->type_forwarders)
3899 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3901 /* Emit MANIFESTRESOURCE table */
3903 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3905 MonoReflectionModuleBuilder *file_module =
3906 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3907 /* The table for the main module is emitted later */
3908 if (file_module != moduleb) {
3910 if (file_module->resources) {
3911 int len = mono_array_length (file_module->resources);
3912 for (j = 0; j < len; ++j) {
3913 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3914 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3922 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3923 * for the modulebuilder @moduleb.
3924 * At the end of the process, method and field tokens are fixed up and the
3925 * on-disk compressed metadata representation is created.
3928 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3930 MonoDynamicTable *table;
3931 MonoDynamicImage *assembly;
3932 MonoReflectionAssemblyBuilder *assemblyb;
3938 assemblyb = moduleb->assemblyb;
3939 assembly = moduleb->dynamic_image;
3940 domain = mono_object_domain (assemblyb);
3942 if (assembly->text_rva)
3945 assembly->text_rva = START_TEXT_RVA;
3947 if (moduleb->is_main) {
3948 mono_image_emit_manifest (moduleb);
3951 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3952 table->rows = 1; /* .<Module> */
3954 alloc_table (table, table->rows);
3956 * Set the first entry.
3958 values = table->values + table->columns;
3959 values [MONO_TYPEDEF_FLAGS] = 0;
3960 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3961 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3962 values [MONO_TYPEDEF_EXTENDS] = 0;
3963 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3964 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3967 * handle global methods
3968 * FIXME: test what to do when global methods are defined in multiple modules.
3970 if (moduleb->global_methods) {
3971 table = &assembly->tables [MONO_TABLE_METHOD];
3972 table->rows += mono_array_length (moduleb->global_methods);
3973 alloc_table (table, table->rows);
3974 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3975 mono_image_get_method_info (
3976 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3978 if (moduleb->global_fields) {
3979 table = &assembly->tables [MONO_TABLE_FIELD];
3980 table->rows += mono_array_length (moduleb->global_fields);
3981 alloc_table (table, table->rows);
3982 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3983 mono_image_get_field_info (
3984 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3987 table = &assembly->tables [MONO_TABLE_MODULE];
3988 alloc_table (table, 1);
3989 mono_image_fill_module_table (domain, moduleb, assembly);
3991 /* Collect all types into a list sorted by their table_idx */
3992 types = g_ptr_array_new ();
3995 for (i = 0; i < moduleb->num_types; ++i) {
3996 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3997 collect_types (types, type);
4000 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4001 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4002 table->rows += types->len;
4003 alloc_table (table, table->rows);
4006 * Emit type names + namespaces at one place inside the string heap,
4007 * so load_class_names () needs to touch fewer pages.
4009 for (i = 0; i < types->len; ++i) {
4010 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4013 n = mono_string_to_utf8 (tb->nspace);
4014 string_heap_insert (&assembly->sheap, n);
4017 for (i = 0; i < types->len; ++i) {
4018 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4021 n = mono_string_to_utf8 (tb->name);
4022 string_heap_insert (&assembly->sheap, n);
4026 for (i = 0; i < types->len; ++i) {
4027 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4028 mono_image_get_type_info (domain, type, assembly);
4032 * table->rows is already set above and in mono_image_fill_module_table.
4034 /* add all the custom attributes at the end, once all the indexes are stable */
4035 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4037 /* CAS assembly permissions */
4038 if (assemblyb->permissions_minimum)
4039 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4040 if (assemblyb->permissions_optional)
4041 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4042 if (assemblyb->permissions_refused)
4043 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4045 module_add_cattrs (assembly, moduleb);
4048 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4050 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4051 * the final tokens and don't need another fixup pass. */
4053 if (moduleb->global_methods) {
4054 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4055 MonoReflectionMethodBuilder *mb = mono_array_get (
4056 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4057 mono_image_add_methodimpl (assembly, mb);
4061 for (i = 0; i < types->len; ++i) {
4062 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4063 if (type->methods) {
4064 for (j = 0; j < type->num_methods; ++j) {
4065 MonoReflectionMethodBuilder *mb = mono_array_get (
4066 type->methods, MonoReflectionMethodBuilder*, j);
4068 mono_image_add_methodimpl (assembly, mb);
4073 g_ptr_array_free (types, TRUE);
4075 fixup_cattrs (assembly);
4079 * mono_image_insert_string:
4080 * @module: module builder object
4083 * Insert @str into the user string stream of @module.
4086 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4088 MonoDynamicImage *assembly;
4093 MONO_ARCH_SAVE_REGS;
4095 if (!module->dynamic_image)
4096 mono_image_module_basic_init (module);
4098 assembly = module->dynamic_image;
4100 if (assembly->save) {
4101 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4102 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4103 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4105 char *swapped = g_malloc (2 * mono_string_length (str));
4106 const char *p = (const char*)mono_string_chars (str);
4108 swap_with_size (swapped, p, 2, mono_string_length (str));
4109 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4113 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4115 mono_image_add_stream_data (&assembly->us, "", 1);
4117 idx = assembly->us.index ++;
4120 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4122 return MONO_TOKEN_STRING | idx;
4126 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4131 klass = obj->vtable->klass;
4132 if (strcmp (klass->name, "MonoMethod") == 0) {
4133 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4134 MonoMethodSignature *sig, *old;
4135 guint32 sig_token, parent;
4138 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4140 nargs = mono_array_length (opt_param_types);
4141 old = mono_method_signature (method);
4142 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4144 sig->hasthis = old->hasthis;
4145 sig->explicit_this = old->explicit_this;
4146 sig->call_convention = old->call_convention;
4147 sig->generic_param_count = old->generic_param_count;
4148 sig->param_count = old->param_count + nargs;
4149 sig->sentinelpos = old->param_count;
4150 sig->ret = old->ret;
4152 for (i = 0; i < old->param_count; i++)
4153 sig->params [i] = old->params [i];
4155 for (i = 0; i < nargs; i++) {
4156 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4157 sig->params [old->param_count + i] = rt->type;
4160 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4161 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4162 parent >>= MONO_TYPEDEFORREF_BITS;
4164 parent <<= MONO_MEMBERREF_PARENT_BITS;
4165 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4167 sig_token = method_encode_signature (assembly, sig);
4168 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4169 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4170 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4171 ReflectionMethodBuilder rmb;
4172 guint32 parent, sig;
4174 reflection_methodbuilder_from_method_builder (&rmb, mb);
4175 rmb.opt_types = opt_param_types;
4177 sig = method_builder_encode_signature (assembly, &rmb);
4179 parent = mono_image_create_token (assembly, obj, TRUE);
4180 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4182 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4183 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4185 token = mono_image_get_varargs_method_token (
4186 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4188 g_error ("requested method token for %s\n", klass->name);
4195 * mono_image_create_token:
4196 * @assembly: a dynamic assembly
4199 * Get a token to insert in the IL code stream for the given MemberInfo.
4200 * @obj can be one of:
4201 * ConstructorBuilder
4211 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4216 klass = obj->vtable->klass;
4217 if (strcmp (klass->name, "MethodBuilder") == 0) {
4218 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4220 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4221 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4223 token = mono_image_get_methodbuilder_token (assembly, mb);
4224 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4225 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4226 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4228 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4229 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4231 token = mono_image_get_ctorbuilder_token (assembly, mb);
4232 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4233 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4234 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4235 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4236 if (tb->generic_params) {
4237 token = mono_image_get_generic_field_token (assembly, fb);
4239 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4241 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4242 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4243 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4244 } else if (strcmp (klass->name, "MonoType") == 0 ||
4245 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4246 MonoReflectionType *tb = (MonoReflectionType *)obj;
4247 token = mono_metadata_token_from_dor (
4248 mono_image_typedef_or_ref (assembly, tb->type));
4249 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4250 MonoReflectionType *tb = (MonoReflectionType *)obj;
4251 token = mono_metadata_token_from_dor (
4252 mono_image_typedef_or_ref (assembly, tb->type));
4253 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4254 strcmp (klass->name, "MonoMethod") == 0 ||
4255 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4256 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4257 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4258 if (m->method->is_inflated) {
4259 if (create_methodspec)
4260 token = mono_image_get_methodspec_token (assembly, m->method);
4262 token = mono_image_get_inflated_method_token (assembly, m->method);
4263 } else if ((m->method->klass->image == &assembly->image) &&
4264 !m->method->klass->generic_class) {
4265 static guint32 method_table_idx = 0xffffff;
4266 if (m->method->klass->wastypebuilder) {
4267 /* we use the same token as the one that was assigned
4268 * to the Methodbuilder.
4269 * FIXME: do the equivalent for Fields.
4271 token = m->method->token;
4274 * Each token should have a unique index, but the indexes are
4275 * assigned by managed code, so we don't know about them. An
4276 * easy solution is to count backwards...
4278 method_table_idx --;
4279 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4282 token = mono_image_get_methodref_token (assembly, m->method);
4284 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4285 } else if (strcmp (klass->name, "MonoField") == 0) {
4286 MonoReflectionField *f = (MonoReflectionField *)obj;
4287 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4288 static guint32 field_table_idx = 0xffffff;
4290 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4292 token = mono_image_get_fieldref_token (assembly, f);
4294 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4295 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4296 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4297 token = mono_image_get_array_token (assembly, m);
4298 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4299 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4300 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4302 g_error ("requested token for %s\n", klass->name);
4305 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4311 guint32 import_lookup_table;
4315 guint32 import_address_table_rva;
4323 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4325 static MonoDynamicImage*
4326 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4328 static const guchar entrycode [16] = {0xff, 0x25, 0};
4329 MonoDynamicImage *image;
4332 const char *version = mono_get_runtime_info ()->runtime_version;
4335 image = GC_MALLOC (sizeof (MonoDynamicImage));
4337 image = g_new0 (MonoDynamicImage, 1);
4340 /*g_print ("created image %p\n", image);*/
4341 /* keep in sync with image.c */
4342 image->image.name = assembly_name;
4343 image->image.assembly_name = image->image.name; /* they may be different */
4344 image->image.module_name = module_name;
4345 image->image.version = g_strdup (version);
4346 image->image.md_version_major = 1;
4347 image->image.md_version_minor = 1;
4348 image->image.dynamic = TRUE;
4350 image->image.references = g_new0 (MonoAssembly*, 1);
4351 image->image.references [0] = NULL;
4353 mono_image_init (&image->image);
4355 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4356 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4357 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4358 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4359 image->handleref = g_hash_table_new (NULL, NULL);
4360 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4361 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4362 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4363 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4364 image->gen_params = g_ptr_array_new ();
4366 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4367 string_heap_init (&image->sheap);
4368 mono_image_add_stream_data (&image->us, "", 1);
4369 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4370 /* import tables... */
4371 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4372 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4373 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4374 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4375 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4376 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4377 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4378 stream_data_align (&image->code);
4380 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4382 for (i=0; i < MONO_TABLE_NUM; ++i) {
4383 image->tables [i].next_idx = 1;
4384 image->tables [i].columns = table_sizes [i];
4387 image->image.assembly = (MonoAssembly*)assembly;
4388 image->run = assembly->run;
4389 image->save = assembly->save;
4390 image->pe_kind = 0x1; /* ILOnly */
4391 image->machine = 0x14c; /* I386 */
4397 * mono_image_basic_init:
4398 * @assembly: an assembly builder object
4400 * Create the MonoImage that represents the assembly builder and setup some
4401 * of the helper hash table and the basic metadata streams.
4404 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4406 MonoDynamicAssembly *assembly;
4407 MonoDynamicImage *image;
4408 MonoDomain *domain = mono_object_domain (assemblyb);
4410 MONO_ARCH_SAVE_REGS;
4412 if (assemblyb->dynamic_assembly)
4416 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4418 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4421 assembly->assembly.ref_count = 1;
4422 assembly->assembly.dynamic = TRUE;
4423 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4424 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4425 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4426 if (assemblyb->culture)
4427 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4429 assembly->assembly.aname.culture = g_strdup ("");
4431 if (assemblyb->version) {
4432 char *vstr = mono_string_to_utf8 (assemblyb->version);
4433 char **version = g_strsplit (vstr, ".", 4);
4434 char **parts = version;
4435 assembly->assembly.aname.major = atoi (*parts++);
4436 assembly->assembly.aname.minor = atoi (*parts++);
4437 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4438 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4440 g_strfreev (version);
4443 assembly->assembly.aname.major = 0;
4444 assembly->assembly.aname.minor = 0;
4445 assembly->assembly.aname.build = 0;
4446 assembly->assembly.aname.revision = 0;
4449 assembly->run = assemblyb->access != 2;
4450 assembly->save = assemblyb->access != 1;
4452 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4453 image->initial_image = TRUE;
4454 assembly->assembly.aname.name = image->image.name;
4455 assembly->assembly.image = &image->image;
4457 mono_domain_assemblies_lock (domain);
4458 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4459 mono_domain_assemblies_unlock (domain);
4461 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4462 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4466 calc_section_size (MonoDynamicImage *assembly)
4470 /* alignment constraints */
4471 assembly->code.index += 3;
4472 assembly->code.index &= ~3;
4473 assembly->meta_size += 3;
4474 assembly->meta_size &= ~3;
4475 assembly->resources.index += 3;
4476 assembly->resources.index &= ~3;
4478 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4479 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4482 if (assembly->win32_res) {
4483 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4485 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4486 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4490 assembly->sections [MONO_SECTION_RELOC].size = 12;
4491 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4501 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4505 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4507 ResTreeNode *t1 = (ResTreeNode*)a;
4508 ResTreeNode *t2 = (ResTreeNode*)b;
4510 return t1->id - t2->id;
4514 * resource_tree_create:
4516 * Organize the resources into a resource tree.
4518 static ResTreeNode *
4519 resource_tree_create (MonoArray *win32_resources)
4521 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4525 tree = g_new0 (ResTreeNode, 1);
4527 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4528 MonoReflectionWin32Resource *win32_res =
4529 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4533 /* FIXME: BUG: this stores managed references in unmanaged memory */
4534 lang_node = g_new0 (ResTreeNode, 1);
4535 lang_node->id = win32_res->lang_id;
4536 lang_node->win32_res = win32_res;
4538 /* Create type node if neccesary */
4540 for (l = tree->children; l; l = l->next)
4541 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4542 type_node = (ResTreeNode*)l->data;
4547 type_node = g_new0 (ResTreeNode, 1);
4548 type_node->id = win32_res->res_type;
4551 * The resource types have to be sorted otherwise
4552 * Windows Explorer can't display the version information.
4554 tree->children = g_slist_insert_sorted (tree->children,
4555 type_node, resource_tree_compare_by_id);
4558 /* Create res node if neccesary */
4560 for (l = type_node->children; l; l = l->next)
4561 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4562 res_node = (ResTreeNode*)l->data;
4567 res_node = g_new0 (ResTreeNode, 1);
4568 res_node->id = win32_res->res_id;
4569 type_node->children = g_slist_append (type_node->children, res_node);
4572 res_node->children = g_slist_append (res_node->children, lang_node);
4579 * resource_tree_encode:
4581 * Encode the resource tree into the format used in the PE file.
4584 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4587 MonoPEResourceDir dir;
4588 MonoPEResourceDirEntry dir_entry;
4589 MonoPEResourceDataEntry data_entry;
4593 * For the format of the resource directory, see the article
4594 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4598 memset (&dir, 0, sizeof (dir));
4599 memset (&dir_entry, 0, sizeof (dir_entry));
4600 memset (&data_entry, 0, sizeof (data_entry));
4602 g_assert (sizeof (dir) == 16);
4603 g_assert (sizeof (dir_entry) == 8);
4604 g_assert (sizeof (data_entry) == 16);
4606 node->offset = p - begin;
4608 /* IMAGE_RESOURCE_DIRECTORY */
4609 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4611 memcpy (p, &dir, sizeof (dir));
4614 /* Reserve space for entries */
4616 p += sizeof (dir_entry) * dir.res_id_entries;
4618 /* Write children */
4619 for (l = node->children; l; l = l->next) {
4620 ResTreeNode *child = (ResTreeNode*)l->data;
4622 if (child->win32_res) {
4624 child->offset = p - begin;
4626 /* IMAGE_RESOURCE_DATA_ENTRY */
4627 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4628 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4630 memcpy (p, &data_entry, sizeof (data_entry));
4631 p += sizeof (data_entry);
4633 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4634 p += data_entry.rde_size;
4636 resource_tree_encode (child, begin, p, &p);
4640 /* IMAGE_RESOURCE_ENTRY */
4641 for (l = node->children; l; l = l->next) {
4642 ResTreeNode *child = (ResTreeNode*)l->data;
4643 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4645 dir_entry.is_dir = child->win32_res ? 0 : 1;
4646 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4648 memcpy (entries, &dir_entry, sizeof (dir_entry));
4649 entries += sizeof (dir_entry);
4656 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4661 MonoReflectionWin32Resource *win32_res;
4664 if (!assemblyb->win32_resources)
4668 * Resources are stored in a three level tree inside the PE file.
4669 * - level one contains a node for each type of resource
4670 * - level two contains a node for each resource
4671 * - level three contains a node for each instance of a resource for a
4672 * specific language.
4675 tree = resource_tree_create (assemblyb->win32_resources);
4677 /* Estimate the size of the encoded tree */
4679 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4680 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4681 size += mono_array_length (win32_res->res_data);
4683 /* Directory structure */
4684 size += mono_array_length (assemblyb->win32_resources) * 256;
4685 p = buf = g_malloc (size);
4687 resource_tree_encode (tree, p, p, &p);
4689 g_assert (p - buf < size);
4691 assembly->win32_res = g_malloc (p - buf);
4692 assembly->win32_res_size = p - buf;
4693 memcpy (assembly->win32_res, buf, p - buf);
4699 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4701 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4704 p += sizeof (MonoPEResourceDir);
4705 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4706 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4707 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4708 if (dir_entry->is_dir) {
4709 fixup_resource_directory (res_section, child, rva);
4711 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4712 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4715 p += sizeof (MonoPEResourceDirEntry);
4720 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4723 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4724 g_error ("WriteFile returned %d\n", GetLastError ());
4728 * mono_image_create_pefile:
4729 * @mb: a module builder object
4731 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4732 * assembly->pefile where it can be easily retrieved later in chunks.
4735 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4736 MonoMSDOSHeader *msdos;
4737 MonoDotNetHeader *header;
4738 MonoSectionTable *section;
4739 MonoCLIHeader *cli_header;
4740 guint32 size, image_size, virtual_base, text_offset;
4741 guint32 header_start, section_start, file_offset, virtual_offset;
4742 MonoDynamicImage *assembly;
4743 MonoReflectionAssemblyBuilder *assemblyb;
4744 MonoDynamicStream pefile_stream = {0};
4745 MonoDynamicStream *pefile = &pefile_stream;
4747 guint32 *rva, value;
4749 static const unsigned char msheader[] = {
4750 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4751 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4752 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4753 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4754 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4755 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4756 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4757 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4760 assemblyb = mb->assemblyb;
4762 mono_image_basic_init (assemblyb);
4763 assembly = mb->dynamic_image;
4765 assembly->pe_kind = assemblyb->pe_kind;
4766 assembly->machine = assemblyb->machine;
4767 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4768 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4770 mono_image_build_metadata (mb);
4772 if (mb->is_main && assemblyb->resources) {
4773 int len = mono_array_length (assemblyb->resources);
4774 for (i = 0; i < len; ++i)
4775 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4778 if (mb->resources) {
4779 int len = mono_array_length (mb->resources);
4780 for (i = 0; i < len; ++i)
4781 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4784 build_compressed_metadata (assembly);
4787 assembly_add_win32_resources (assembly, assemblyb);
4789 nsections = calc_section_size (assembly);
4791 /* The DOS header and stub */
4792 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4793 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4795 /* the dotnet header */
4796 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4798 /* the section tables */
4799 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4801 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4802 virtual_offset = VIRT_ALIGN;
4805 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4806 if (!assembly->sections [i].size)
4809 file_offset += FILE_ALIGN - 1;
4810 file_offset &= ~(FILE_ALIGN - 1);
4811 virtual_offset += VIRT_ALIGN - 1;
4812 virtual_offset &= ~(VIRT_ALIGN - 1);
4814 assembly->sections [i].offset = file_offset;
4815 assembly->sections [i].rva = virtual_offset;
4817 file_offset += assembly->sections [i].size;
4818 virtual_offset += assembly->sections [i].size;
4819 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4822 file_offset += FILE_ALIGN - 1;
4823 file_offset &= ~(FILE_ALIGN - 1);
4825 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4827 /* back-patch info */
4828 msdos = (MonoMSDOSHeader*)pefile->data;
4829 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4831 header = (MonoDotNetHeader*)(pefile->data + header_start);
4832 header->pesig [0] = 'P';
4833 header->pesig [1] = 'E';
4835 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4836 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4837 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4838 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4839 if (assemblyb->pekind == 1) {
4841 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4844 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4847 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4849 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4850 header->pe.pe_major = 6;
4851 header->pe.pe_minor = 0;
4852 size = assembly->sections [MONO_SECTION_TEXT].size;
4853 size += FILE_ALIGN - 1;
4854 size &= ~(FILE_ALIGN - 1);
4855 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4856 size = assembly->sections [MONO_SECTION_RSRC].size;
4857 size += FILE_ALIGN - 1;
4858 size &= ~(FILE_ALIGN - 1);
4859 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4860 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4861 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4862 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4863 /* pe_rva_entry_point always at the beginning of the text section */
4864 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4866 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4867 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4868 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4869 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4870 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4871 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4872 size = section_start;
4873 size += FILE_ALIGN - 1;
4874 size &= ~(FILE_ALIGN - 1);
4875 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4877 size += VIRT_ALIGN - 1;
4878 size &= ~(VIRT_ALIGN - 1);
4879 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4882 // Translate the PEFileKind value to the value expected by the Windows loader
4888 // PEFileKinds.Dll == 1
4889 // PEFileKinds.ConsoleApplication == 2
4890 // PEFileKinds.WindowApplication == 3
4893 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4894 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4896 if (assemblyb->pekind == 3)
4901 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4903 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4904 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4905 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4906 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4907 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4908 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4910 /* fill data directory entries */
4912 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4913 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4915 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4916 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4918 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4919 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4920 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4921 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4922 /* patch entrypoint name */
4923 if (assemblyb->pekind == 1)
4924 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4926 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4927 /* patch imported function RVA name */
4928 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4929 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4931 /* the import table */
4932 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4933 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4934 /* patch imported dll RVA name and other entries in the dir */
4935 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4936 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4937 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4938 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4939 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4940 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4942 p = (assembly->code.data + assembly->ilt_offset);
4943 value = (assembly->text_rva + assembly->imp_names_offset);
4944 *p++ = (value) & 0xff;
4945 *p++ = (value >> 8) & (0xff);
4946 *p++ = (value >> 16) & (0xff);
4947 *p++ = (value >> 24) & (0xff);
4949 /* the CLI header info */
4950 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4951 cli_header->ch_size = GUINT32_FROM_LE (72);
4952 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4953 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4954 if (assemblyb->entry_point) {
4955 guint32 table_idx = 0;
4956 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4957 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4958 table_idx = methodb->table_idx;
4960 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4962 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4964 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4966 /* The embedded managed resources */
4967 text_offset = assembly->text_rva + assembly->code.index;
4968 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4969 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4970 text_offset += assembly->resources.index;
4971 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4972 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4973 text_offset += assembly->meta_size;
4974 if (assembly->strong_name_size) {
4975 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4976 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4977 text_offset += assembly->strong_name_size;
4980 /* write the section tables and section content */
4981 section = (MonoSectionTable*)(pefile->data + section_start);
4982 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4983 static const char *section_names [] = {
4984 ".text", ".rsrc", ".reloc"
4986 if (!assembly->sections [i].size)
4988 strcpy (section->st_name, section_names [i]);
4989 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4990 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4991 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4992 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4993 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4994 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4995 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4999 checked_write_file (file, pefile->data, pefile->index);
5001 mono_dynamic_stream_reset (pefile);
5003 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5004 if (!assembly->sections [i].size)
5007 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5008 g_error ("SetFilePointer returned %d\n", GetLastError ());
5011 case MONO_SECTION_TEXT:
5012 /* patch entry point */
5013 p = (assembly->code.data + 2);
5014 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5015 *p++ = (value) & 0xff;
5016 *p++ = (value >> 8) & 0xff;
5017 *p++ = (value >> 16) & 0xff;
5018 *p++ = (value >> 24) & 0xff;
5020 checked_write_file (file, assembly->code.data, assembly->code.index);
5021 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5022 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5023 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5026 g_free (assembly->image.raw_metadata);
5028 case MONO_SECTION_RELOC: {
5032 guint16 type_and_offset;
5036 g_assert (sizeof (reloc) == 12);
5038 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5039 reloc.block_size = GUINT32_FROM_LE (12);
5042 * the entrypoint is always at the start of the text section
5043 * 3 is IMAGE_REL_BASED_HIGHLOW
5044 * 2 is patch_size_rva - text_rva
5046 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5049 checked_write_file (file, &reloc, sizeof (reloc));
5053 case MONO_SECTION_RSRC:
5054 if (assembly->win32_res) {
5056 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5057 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5058 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5062 g_assert_not_reached ();
5066 /* check that the file is properly padded */
5067 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5068 g_error ("SetFilePointer returned %d\n", GetLastError ());
5069 if (! SetEndOfFile (file))
5070 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5072 mono_dynamic_stream_reset (&assembly->code);
5073 mono_dynamic_stream_reset (&assembly->us);
5074 mono_dynamic_stream_reset (&assembly->blob);
5075 mono_dynamic_stream_reset (&assembly->guid);
5076 mono_dynamic_stream_reset (&assembly->sheap);
5078 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5079 g_hash_table_destroy (assembly->blob_cache);
5080 assembly->blob_cache = NULL;
5083 MonoReflectionModule *
5084 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5088 MonoImageOpenStatus status;
5089 MonoDynamicAssembly *assembly;
5090 guint32 module_count;
5091 MonoImage **new_modules;
5093 name = mono_string_to_utf8 (fileName);
5095 image = mono_image_open (name, &status);
5098 if (status == MONO_IMAGE_ERROR_ERRNO)
5099 exc = mono_get_exception_file_not_found (fileName);
5101 exc = mono_get_exception_bad_image_format (name);
5103 mono_raise_exception (exc);
5108 assembly = ab->dynamic_assembly;
5109 image->assembly = (MonoAssembly*)assembly;
5111 module_count = image->assembly->image->module_count;
5112 new_modules = g_new0 (MonoImage *, module_count + 1);
5114 if (image->assembly->image->modules)
5115 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5116 new_modules [module_count] = image;
5117 mono_image_addref (image);
5119 g_free (image->assembly->image->modules);
5120 image->assembly->image->modules = new_modules;
5121 image->assembly->image->module_count ++;
5123 mono_assembly_load_references (image, &status);
5125 mono_image_close (image);
5126 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5129 return mono_module_get_object (mono_domain_get (), image);
5133 * We need to return always the same object for MethodInfo, FieldInfo etc..
5134 * but we need to consider the reflected type.
5135 * type uses a different hash, since it uses custom hash/equal functions.
5140 MonoClass *refclass;
5144 reflected_equal (gconstpointer a, gconstpointer b) {
5145 const ReflectedEntry *ea = a;
5146 const ReflectedEntry *eb = b;
5148 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5152 reflected_hash (gconstpointer a) {
5153 const ReflectedEntry *ea = a;
5154 return mono_aligned_addr_hash (ea->item);
5157 #define CHECK_OBJECT(t,p,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 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5167 mono_domain_unlock (domain); \
5170 mono_domain_unlock (domain); \
5174 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5176 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5178 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5181 #define CACHE_OBJECT(t,p,o,k) \
5184 ReflectedEntry pe; \
5186 pe.refclass = (k); \
5187 mono_domain_lock (domain); \
5188 if (!domain->refobject_hash) \
5189 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5190 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5192 ReflectedEntry *e = ALLOC_REFENTRY; \
5194 e->refclass = (k); \
5195 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5198 mono_domain_unlock (domain); \
5203 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5205 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5209 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5211 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5215 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5217 MonoDynamicImage *image = moduleb->dynamic_image;
5218 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5221 MonoImage **new_modules;
5224 * FIXME: we already created an image in mono_image_basic_init (), but
5225 * we don't know which module it belongs to, since that is only
5226 * determined at assembly save time.
5228 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5229 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5231 moduleb->module.image = &image->image;
5232 moduleb->dynamic_image = image;
5233 register_module (mono_object_domain (moduleb), moduleb, image);
5235 /* register the module with the assembly */
5236 ass = ab->dynamic_assembly->assembly.image;
5237 module_count = ass->module_count;
5238 new_modules = g_new0 (MonoImage *, module_count + 1);
5241 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5242 new_modules [module_count] = &image->image;
5243 mono_image_addref (&image->image);
5245 g_free (ass->modules);
5246 ass->modules = new_modules;
5247 ass->module_count ++;
5252 * mono_assembly_get_object:
5253 * @domain: an app domain
5254 * @assembly: an assembly
5256 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5258 MonoReflectionAssembly*
5259 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5261 static MonoClass *System_Reflection_Assembly;
5262 MonoReflectionAssembly *res;
5264 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5265 if (!System_Reflection_Assembly)
5266 System_Reflection_Assembly = mono_class_from_name (
5267 mono_defaults.corlib, "System.Reflection", "Assembly");
5268 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5269 res->assembly = assembly;
5271 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5276 MonoReflectionModule*
5277 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5279 static MonoClass *System_Reflection_Module;
5280 MonoReflectionModule *res;
5283 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5284 if (!System_Reflection_Module)
5285 System_Reflection_Module = mono_class_from_name (
5286 mono_defaults.corlib, "System.Reflection", "Module");
5287 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5290 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5292 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5293 basename = g_path_get_basename (image->name);
5294 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5295 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5299 if (image->assembly->image == image) {
5300 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5303 g_assert (image->assembly->image->modules);
5305 for (i = 0; i < image->assembly->image->module_count; i++) {
5306 if (image->assembly->image->modules [i] == image)
5307 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5309 g_assert (res->token);
5312 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5315 MonoReflectionModule*
5316 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5318 static MonoClass *System_Reflection_Module;
5319 MonoReflectionModule *res;
5320 MonoTableInfo *table;
5321 guint32 cols [MONO_FILE_SIZE];
5323 guint32 i, name_idx;
5326 if (!System_Reflection_Module)
5327 System_Reflection_Module = mono_class_from_name (
5328 mono_defaults.corlib, "System.Reflection", "Module");
5329 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5331 table = &image->tables [MONO_TABLE_FILE];
5332 g_assert (table_index < table->rows);
5333 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5336 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5337 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5339 /* Check whenever the row has a corresponding row in the moduleref table */
5340 table = &image->tables [MONO_TABLE_MODULEREF];
5341 for (i = 0; i < table->rows; ++i) {
5342 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5343 val = mono_metadata_string_heap (image, name_idx);
5344 if (strcmp (val, name) == 0)
5345 res->image = image->modules [i];
5348 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5349 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5350 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5351 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5352 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5358 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5360 if ((t1->type != t2->type) ||
5361 (t1->byref != t2->byref))
5365 case MONO_TYPE_VOID:
5366 case MONO_TYPE_BOOLEAN:
5367 case MONO_TYPE_CHAR:
5378 case MONO_TYPE_STRING:
5381 case MONO_TYPE_OBJECT:
5382 case MONO_TYPE_TYPEDBYREF:
5384 case MONO_TYPE_VALUETYPE:
5385 case MONO_TYPE_CLASS:
5386 case MONO_TYPE_SZARRAY:
5387 return t1->data.klass == t2->data.klass;
5389 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5390 case MONO_TYPE_ARRAY:
5391 if (t1->data.array->rank != t2->data.array->rank)
5393 return t1->data.array->eklass == t2->data.array->eklass;
5394 case MONO_TYPE_GENERICINST: {
5396 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5398 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5399 &t2->data.generic_class->container_class->byval_arg))
5401 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5402 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5408 case MONO_TYPE_MVAR:
5409 return t1->data.generic_param == t2->data.generic_param;
5411 g_error ("implement type compare for %0x!", t1->type);
5419 mymono_metadata_type_hash (MonoType *t1)
5425 hash |= t1->byref << 6; /* do not collide with t1->type values */
5427 case MONO_TYPE_VALUETYPE:
5428 case MONO_TYPE_CLASS:
5429 case MONO_TYPE_SZARRAY:
5430 /* check if the distribution is good enough */
5431 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5433 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5434 case MONO_TYPE_GENERICINST: {
5436 MonoGenericInst *inst = t1->data.generic_class->inst;
5437 hash += g_str_hash (t1->data.generic_class->container_class->name);
5439 for (i = 0; i < inst->type_argc; ++i) {
5440 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5449 static MonoReflectionGenericClass*
5450 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5452 static MonoClass *System_Reflection_MonoGenericClass;
5453 MonoReflectionGenericClass *res;
5454 MonoInflatedGenericClass *gclass;
5457 if (!System_Reflection_MonoGenericClass) {
5458 System_Reflection_MonoGenericClass = mono_class_from_name (
5459 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5460 g_assert (System_Reflection_MonoGenericClass);
5463 gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
5464 gklass = gclass->generic_class.container_class;
5465 g_assert (gklass->generic_container);
5467 mono_class_init (gclass->klass);
5469 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5471 res->type.type = geninst;
5472 if (gklass->wastypebuilder && gklass->reflection_info)
5473 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5475 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5481 verify_safe_for_managed_space (MonoType *type)
5483 switch (type->type) {
5485 case MONO_TYPE_ARRAY:
5486 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5488 return verify_safe_for_managed_space (type->data.type);
5489 case MONO_TYPE_SZARRAY:
5490 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5491 case MONO_TYPE_GENERICINST: {
5492 MonoGenericInst *inst = type->data.generic_class->inst;
5496 for (i = 0; i < inst->type_argc; ++i)
5497 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5503 case MONO_TYPE_MVAR:
5510 * mono_type_get_object:
5511 * @domain: an app domain
5514 * Return an System.MonoType object representing the type @type.
5517 mono_type_get_object (MonoDomain *domain, MonoType *type)
5519 MonoReflectionType *res;
5520 MonoClass *klass = mono_class_from_mono_type (type);
5522 mono_domain_lock (domain);
5523 if (!domain->type_hash)
5524 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5525 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5526 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5527 mono_domain_unlock (domain);
5530 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5531 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5532 mono_g_hash_table_insert (domain->type_hash, type, res);
5533 mono_domain_unlock (domain);
5537 if (!verify_safe_for_managed_space (type)) {
5538 mono_domain_unlock (domain);
5539 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5542 if (klass->reflection_info && !klass->wastypebuilder) {
5543 /* g_assert_not_reached (); */
5544 /* should this be considered an error condition? */
5546 mono_domain_unlock (domain);
5547 return klass->reflection_info;
5550 mono_class_init (klass);
5552 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5554 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5557 mono_g_hash_table_insert (domain->type_hash, type, res);
5558 mono_domain_unlock (domain);
5563 * mono_method_get_object:
5564 * @domain: an app domain
5566 * @refclass: the reflected type (can be NULL)
5568 * Return an System.Reflection.MonoMethod object representing the method @method.
5570 MonoReflectionMethod*
5571 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5574 * We use the same C representation for methods and constructors, but the type
5575 * name in C# is different.
5579 MonoReflectionMethod *ret;
5581 if (method->is_inflated) {
5582 MonoReflectionGenericMethod *gret;
5584 method = mono_get_inflated_method (method);
5585 refclass = method->klass;
5586 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5587 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5588 cname = "MonoGenericCMethod";
5590 cname = "MonoGenericMethod";
5591 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5593 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5594 gret->method.method = method;
5595 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5596 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5597 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5601 refclass = method->klass;
5603 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5604 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5605 cname = "MonoCMethod";
5607 cname = "MonoMethod";
5608 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5610 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5611 ret->method = method;
5612 MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name));
5613 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5614 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5618 * mono_field_get_object:
5619 * @domain: an app domain
5623 * Return an System.Reflection.MonoField object representing the field @field
5626 MonoReflectionField*
5627 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5629 MonoReflectionField *res;
5632 CHECK_OBJECT (MonoReflectionField *, field, klass);
5633 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5634 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5637 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5638 if (field->generic_info)
5639 res->attrs = field->generic_info->generic_type->attrs;
5641 res->attrs = field->type->attrs;
5642 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5643 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5647 * mono_property_get_object:
5648 * @domain: an app domain
5650 * @property: a property
5652 * Return an System.Reflection.MonoProperty object representing the property @property
5655 MonoReflectionProperty*
5656 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5658 MonoReflectionProperty *res;
5661 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5662 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5663 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5665 res->property = property;
5666 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5670 * mono_event_get_object:
5671 * @domain: an app domain
5675 * Return an System.Reflection.MonoEvent object representing the event @event
5678 MonoReflectionEvent*
5679 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5681 MonoReflectionEvent *res;
5684 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5685 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5686 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5689 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5693 * mono_param_get_objects:
5694 * @domain: an app domain
5697 * Return an System.Reflection.ParameterInfo array object representing the parameters
5698 * in the method @method.
5701 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5703 static MonoClass *System_Reflection_ParameterInfo;
5704 MonoArray *res = NULL;
5705 MonoReflectionMethod *member = NULL;
5706 MonoReflectionParameter *param = NULL;
5707 char **names, **blobs = NULL;
5708 guint32 *types = NULL;
5709 MonoType *type = NULL;
5710 MonoObject *dbnull = mono_get_dbnull_object (domain);
5711 MonoMarshalSpec **mspecs;
5712 MonoMethodSignature *sig;
5715 if (!System_Reflection_ParameterInfo)
5716 System_Reflection_ParameterInfo = mono_class_from_name (
5717 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5719 if (!mono_method_signature (method)->param_count)
5720 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5722 /* Note: the cache is based on the address of the signature into the method
5723 * since we already cache MethodInfos with the method as keys.
5725 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5727 sig = mono_method_signature (method);
5728 member = mono_method_get_object (domain, method, NULL);
5729 names = g_new (char *, sig->param_count);
5730 mono_method_get_param_names (method, (const char **) names);
5732 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5733 mono_method_get_marshal_info (method, mspecs);
5735 res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5736 for (i = 0; i < sig->param_count; ++i) {
5737 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5738 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5739 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5740 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5741 param->PositionImpl = i;
5742 param->AttrsImpl = sig->params [i]->attrs;
5744 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5745 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5749 blobs = g_new0 (char *, sig->param_count);
5750 types = g_new0 (guint32, sig->param_count);
5751 get_default_param_value_blobs (method, blobs, types);
5754 /* Build MonoType for the type from the Constant Table */
5756 type = g_new0 (MonoType, 1);
5757 type->type = types [i];
5758 type->data.klass = NULL;
5759 if (types [i] == MONO_TYPE_CLASS)
5760 type->data.klass = mono_defaults.object_class;
5761 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5762 /* For enums, types [i] contains the base type */
5764 type->type = MONO_TYPE_VALUETYPE;
5765 type->data.klass = mono_class_from_mono_type (sig->params [i]);
5767 type->data.klass = mono_class_from_mono_type (type);
5769 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5771 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5772 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5773 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5778 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5780 mono_array_setref (res, i, param);
5787 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5789 mono_metadata_free_marshal_spec (mspecs [i]);
5792 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5796 * mono_method_body_get_object:
5797 * @domain: an app domain
5800 * Return an System.Reflection.MethodBody object representing the method @method.
5802 MonoReflectionMethodBody*
5803 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5805 static MonoClass *System_Reflection_MethodBody = NULL;
5806 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5807 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5808 MonoReflectionMethodBody *ret;
5809 MonoMethodNormal *mn;
5810 MonoMethodHeader *header;
5811 guint32 method_rva, local_var_sig_token;
5813 unsigned char format, flags;
5816 if (!System_Reflection_MethodBody)
5817 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5818 if (!System_Reflection_LocalVariableInfo)
5819 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5820 if (!System_Reflection_ExceptionHandlingClause)
5821 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5823 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5825 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5826 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5827 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5828 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5830 mn = (MonoMethodNormal *)method;
5831 header = mono_method_get_header (method);
5833 /* Obtain local vars signature token */
5834 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5835 ptr = mono_image_rva_map (method->klass->image, method_rva);
5836 flags = *(const unsigned char *) ptr;
5837 format = flags & METHOD_HEADER_FORMAT_MASK;
5839 case METHOD_HEADER_TINY_FORMAT:
5840 case METHOD_HEADER_TINY_FORMAT1:
5841 local_var_sig_token = 0;
5843 case METHOD_HEADER_FAT_FORMAT:
5847 local_var_sig_token = read32 (ptr);
5850 g_assert_not_reached ();
5853 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5855 ret->init_locals = header->init_locals;
5856 ret->max_stack = header->max_stack;
5857 ret->local_var_sig_token = local_var_sig_token;
5858 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5859 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5862 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5863 for (i = 0; i < header->num_locals; ++i) {
5864 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5865 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5866 info->is_pinned = header->locals [i]->pinned;
5867 info->local_index = i;
5868 mono_array_setref (ret->locals, i, info);
5872 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5873 for (i = 0; i < header->num_clauses; ++i) {
5874 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5875 MonoExceptionClause *clause = &header->clauses [i];
5877 info->flags = clause->flags;
5878 info->try_offset = clause->try_offset;
5879 info->try_length = clause->try_len;
5880 info->handler_offset = clause->handler_offset;
5881 info->handler_length = clause->handler_len;
5882 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5883 info->filter_offset = clause->data.filter_offset;
5884 else if (clause->data.catch_class)
5885 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5887 mono_array_setref (ret->clauses, i, info);
5890 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5895 mono_get_dbnull_object (MonoDomain *domain)
5899 static MonoClassField *dbnull_value_field = NULL;
5901 if (!dbnull_value_field) {
5902 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5903 mono_class_init (klass);
5904 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5905 g_assert (dbnull_value_field);
5907 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5914 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5916 guint32 param_index, i, lastp, crow = 0;
5917 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5920 MonoClass *klass = method->klass;
5921 MonoImage *image = klass->image;
5922 MonoMethodSignature *methodsig = mono_method_signature (method);
5924 MonoTableInfo *constt;
5925 MonoTableInfo *methodt;
5926 MonoTableInfo *paramt;
5928 if (!methodsig->param_count)
5931 mono_class_init (klass);
5933 if (klass->image->dynamic) {
5934 MonoReflectionMethodAux *aux;
5935 if (method->is_inflated)
5936 method = ((MonoMethodInflated*)method)->declaring;
5937 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5938 if (aux && aux->param_defaults) {
5939 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5940 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5945 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5946 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5947 constt = &image->tables [MONO_TABLE_CONSTANT];
5949 idx = mono_method_get_index (method) - 1;
5950 g_assert (idx != -1);
5952 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5953 if (idx + 1 < methodt->rows)
5954 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5956 lastp = paramt->rows + 1;
5958 for (i = param_index; i < lastp; ++i) {
5961 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5962 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5964 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5967 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5972 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5973 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5974 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5981 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5986 MonoType *basetype = type;
5991 klass = mono_class_from_mono_type (type);
5992 if (klass->valuetype) {
5993 object = mono_object_new (domain, klass);
5994 retval = ((gchar *) object + sizeof (MonoObject));
5995 if (klass->enumtype)
5996 basetype = klass->enum_basetype;
6001 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6008 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6012 memset (assembly, 0, sizeof (MonoAssemblyName));
6014 assembly->culture = "";
6015 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6017 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6020 while (g_ascii_isspace (*p) || *p == ',') {
6029 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6031 assembly->major = strtoul (p, &s, 10);
6032 if (s == p || *s != '.')
6035 assembly->minor = strtoul (p, &s, 10);
6036 if (s == p || *s != '.')
6039 assembly->build = strtoul (p, &s, 10);
6040 if (s == p || *s != '.')
6043 assembly->revision = strtoul (p, &s, 10);
6047 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6049 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6050 assembly->culture = "";
6053 assembly->culture = p;
6054 while (*p && *p != ',') {
6058 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6060 if (strncmp (p, "null", 4) == 0) {
6065 while (*p && *p != ',') {
6068 len = (p - start + 1);
6069 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6070 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6071 g_strlcpy (assembly->public_key_token, start, len);
6074 while (*p && *p != ',')
6078 while (g_ascii_isspace (*p) || *p == ',') {
6092 * mono_reflection_parse_type:
6095 * Parse a type name as accepted by the GetType () method and output the info
6096 * extracted in the info structure.
6097 * the name param will be mangled, so, make a copy before passing it to this function.
6098 * The fields in info will be valid until the memory pointed to by name is valid.
6100 * See also mono_type_get_name () below.
6102 * Returns: 0 on parse error.
6105 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6106 MonoTypeNameParse *info)
6108 char *start, *p, *w, *temp, *last_point, *startn;
6109 int in_modifiers = 0;
6110 int isbyref = 0, rank, arity = 0, i;
6112 start = p = w = name;
6114 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6115 info->name = info->name_space = NULL;
6116 info->nested = NULL;
6117 info->modifiers = NULL;
6118 info->type_arguments = NULL;
6120 /* last_point separates the namespace from the name */
6126 *p = 0; /* NULL terminate the name */
6128 info->nested = g_list_append (info->nested, startn);
6129 /* we have parsed the nesting namespace + name */
6133 info->name_space = start;
6135 info->name = last_point + 1;
6137 info->name_space = (char *)"";
6156 i = strtol (p, &temp, 10);
6173 info->name_space = start;
6175 info->name = last_point + 1;
6177 info->name_space = (char *)"";
6184 if (isbyref) /* only one level allowed by the spec */
6187 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6191 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6197 info->type_arguments = g_ptr_array_new ();
6198 for (i = 0; i < arity; i++) {
6199 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6200 gboolean fqname = FALSE;
6202 g_ptr_array_add (info->type_arguments, subinfo);
6209 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6220 while (*p && (*p != ']'))
6228 if (g_ascii_isspace (*aname)) {
6235 !assembly_name_to_aname (&subinfo->assembly, aname))
6239 if (i + 1 < arity) {
6259 else if (*p != '*') /* '*' means unknown lower bound */
6265 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6276 if (g_ascii_isspace (*p)) {
6283 return 0; /* missing assembly name */
6284 if (!assembly_name_to_aname (&info->assembly, p))
6290 if (info->assembly.name)
6293 // *w = 0; /* terminate class name */
6295 if (!info->name || !*info->name)
6299 /* add other consistency checks */
6304 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6306 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6310 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6312 gboolean type_resolve = FALSE;
6315 if (info->assembly.name) {
6316 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6318 /* then we must load the assembly ourselve - see #60439 */
6319 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6323 image = assembly->image;
6324 } else if (!image) {
6325 image = mono_defaults.corlib;
6328 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6329 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6330 image = mono_defaults.corlib;
6331 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6338 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6345 image = mono_defaults.corlib;
6348 klass = mono_class_from_name_case (image, info->name_space, info->name);
6350 klass = mono_class_from_name (image, info->name_space, info->name);
6353 for (mod = info->nested; mod; mod = mod->next) {
6356 mono_class_init (klass);
6357 nested = klass->nested_classes;
6360 klass = nested->data;
6362 if (g_strcasecmp (klass->name, mod->data) == 0)
6365 if (strcmp (klass->name, mod->data) == 0)
6369 nested = nested->next;
6376 mono_class_init (klass);
6378 if (info->type_arguments) {
6379 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6380 MonoReflectionType *the_type;
6384 for (i = 0; i < info->type_arguments->len; i++) {
6385 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6387 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6388 if (!type_args [i]) {
6394 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6396 instance = mono_reflection_bind_generic_parameters (
6397 the_type, info->type_arguments->len, type_args);
6404 klass = mono_class_from_mono_type (instance);
6407 for (mod = info->modifiers; mod; mod = mod->next) {
6408 modval = GPOINTER_TO_UINT (mod->data);
6409 if (!modval) { /* byref: must be last modifier */
6410 return &klass->this_arg;
6411 } else if (modval == -1) {
6412 klass = mono_ptr_class_get (&klass->byval_arg);
6413 } else { /* array rank */
6414 klass = mono_array_class_get (klass, modval);
6416 mono_class_init (klass);
6419 return &klass->byval_arg;
6423 * mono_reflection_get_type:
6424 * @image: a metadata context
6425 * @info: type description structure
6426 * @ignorecase: flag for case-insensitive string compares
6427 * @type_resolve: whenever type resolve was already tried
6429 * Build a MonoType from the type description in @info.
6434 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6437 MonoReflectionAssembly *assembly;
6441 type = mono_reflection_get_type_internal (image, info, ignorecase);
6444 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6451 *type_resolve = TRUE;
6454 /* Reconstruct the type name */
6455 fullName = g_string_new ("");
6456 if (info->name_space && (info->name_space [0] != '\0'))
6457 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6459 g_string_printf (fullName, info->name);
6460 for (mod = info->nested; mod; mod = mod->next)
6461 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6463 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6465 if (assembly->assembly->dynamic) {
6466 /* Enumerate all modules */
6467 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6471 if (abuilder->modules) {
6472 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6473 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6474 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6480 if (!type && abuilder->loaded_modules) {
6481 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6482 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6483 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6490 type = mono_reflection_get_type_internal (assembly->assembly->image,
6493 g_string_free (fullName, TRUE);
6498 free_type_info (MonoTypeNameParse *info)
6500 g_list_free (info->modifiers);
6501 g_list_free (info->nested);
6503 if (info->type_arguments) {
6506 for (i = 0; i < info->type_arguments->len; i++) {
6507 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6509 free_type_info (subinfo);
6512 g_ptr_array_free (info->type_arguments, TRUE);
6517 * mono_reflection_type_from_name:
6519 * @image: a metadata context (can be NULL).
6521 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6522 * it defaults to get the type from @image or, if @image is NULL or loading
6523 * from it fails, uses corlib.
6527 mono_reflection_type_from_name (char *name, MonoImage *image)
6529 MonoType *type = NULL;
6530 MonoTypeNameParse info;
6533 /* Make a copy since parse_type modifies its argument */
6534 tmp = g_strdup (name);
6536 /*g_print ("requested type %s\n", str);*/
6537 if (mono_reflection_parse_type (tmp, &info)) {
6538 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6542 free_type_info (&info);
6547 * mono_reflection_get_token:
6549 * Return the metadata token of OBJ which should be an object
6550 * representing a metadata element.
6553 mono_reflection_get_token (MonoObject *obj)
6558 klass = obj->vtable->klass;
6560 if (strcmp (klass->name, "MethodBuilder") == 0) {
6561 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6563 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6564 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6565 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6567 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6568 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6569 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6570 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6571 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6572 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6573 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6574 } else if (strcmp (klass->name, "MonoType") == 0) {
6575 MonoReflectionType *tb = (MonoReflectionType *)obj;
6576 token = mono_class_from_mono_type (tb->type)->type_token;
6577 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6578 strcmp (klass->name, "MonoMethod") == 0 ||
6579 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6580 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6581 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6582 if (m->method->is_inflated) {
6583 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6584 return inflated->declaring->token;
6586 token = m->method->token;
6588 } else if (strcmp (klass->name, "MonoField") == 0) {
6589 MonoReflectionField *f = (MonoReflectionField*)obj;
6591 if (f->field->generic_info && f->field->generic_info->reflection_info)
6592 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6594 token = mono_class_get_field_token (f->field);
6595 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6596 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6598 token = mono_class_get_property_token (p->property);
6599 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6600 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6602 token = mono_class_get_event_token (p->event);
6603 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6604 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6606 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6607 } else if (strcmp (klass->name, "Module") == 0) {
6608 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6611 } else if (strcmp (klass->name, "Assembly") == 0) {
6612 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6614 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6615 MonoException *ex = mono_get_exception_not_implemented (msg);
6617 mono_raise_exception (ex);
6624 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6626 int slen, type = t->type;
6627 MonoClass *tklass = t->data.klass;
6633 case MONO_TYPE_BOOLEAN: {
6634 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6639 case MONO_TYPE_CHAR:
6641 case MONO_TYPE_I2: {
6642 guint16 *val = g_malloc (sizeof (guint16));
6647 #if SIZEOF_VOID_P == 4
6653 case MONO_TYPE_I4: {
6654 guint32 *val = g_malloc (sizeof (guint32));
6659 #if SIZEOF_VOID_P == 8
6660 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6665 case MONO_TYPE_I8: {
6666 guint64 *val = g_malloc (sizeof (guint64));
6671 case MONO_TYPE_VALUETYPE:
6672 if (t->data.klass->enumtype) {
6673 type = t->data.klass->enum_basetype->type;
6676 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6679 case MONO_TYPE_STRING:
6680 if (*p == (char)0xFF) {
6684 slen = mono_metadata_decode_value (p, &p);
6686 return mono_string_new_len (mono_domain_get (), p, slen);
6687 case MONO_TYPE_CLASS: {
6690 if (*p == (char)0xFF) {
6695 slen = mono_metadata_decode_value (p, &p);
6696 n = g_memdup (p, slen + 1);
6698 t = mono_reflection_type_from_name (n, image);
6700 g_warning ("Cannot load type '%s'", n);
6704 return mono_type_get_object (mono_domain_get (), t);
6708 case MONO_TYPE_OBJECT: {
6711 MonoClass *subc = NULL;
6716 } else if (subt == 0x0E) {
6717 type = MONO_TYPE_STRING;
6719 } else if (subt == 0x1D) {
6720 MonoType simple_type = {{0}};
6724 type = MONO_TYPE_SZARRAY;
6725 simple_type.type = etype;
6726 tklass = mono_class_from_mono_type (&simple_type);
6728 } else if (subt == 0x55) {
6731 slen = mono_metadata_decode_value (p, &p);
6732 n = g_memdup (p, slen + 1);
6734 t = mono_reflection_type_from_name (n, image);
6736 g_warning ("Cannot load type '%s'", n);
6739 subc = mono_class_from_mono_type (t);
6740 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6741 MonoType simple_type = {{0}};
6742 simple_type.type = subt;
6743 subc = mono_class_from_mono_type (&simple_type);
6745 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6747 val = load_cattr_value (image, &subc->byval_arg, p, end);
6748 obj = mono_object_new (mono_domain_get (), subc);
6749 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6753 case MONO_TYPE_SZARRAY: {
6755 guint32 i, alen, basetype;
6758 if (alen == 0xffffffff) {
6762 arr = mono_array_new (mono_domain_get(), tklass, alen);
6763 basetype = tklass->byval_arg.type;
6768 case MONO_TYPE_BOOLEAN:
6769 for (i = 0; i < alen; i++) {
6770 MonoBoolean val = *p++;
6771 mono_array_set (arr, MonoBoolean, i, val);
6774 case MONO_TYPE_CHAR:
6777 for (i = 0; i < alen; i++) {
6778 guint16 val = read16 (p);
6779 mono_array_set (arr, guint16, i, val);
6786 for (i = 0; i < alen; i++) {
6787 guint32 val = read32 (p);
6788 mono_array_set (arr, guint32, i, val);
6795 for (i = 0; i < alen; i++) {
6796 guint64 val = read64 (p);
6797 mono_array_set (arr, guint64, i, val);
6801 case MONO_TYPE_CLASS:
6802 case MONO_TYPE_OBJECT:
6803 case MONO_TYPE_STRING:
6804 for (i = 0; i < alen; i++) {
6805 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6806 mono_array_setref (arr, i, item);
6810 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6816 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6822 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6824 static MonoClass *klass;
6825 static MonoMethod *ctor;
6827 void *params [2], *unboxed;
6830 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6832 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6834 params [0] = mono_type_get_object (mono_domain_get (), t);
6836 retval = mono_object_new (mono_domain_get (), klass);
6837 unboxed = mono_object_unbox (retval);
6838 mono_runtime_invoke (ctor, unboxed, params, NULL);
6844 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6846 static MonoClass *klass;
6847 static MonoMethod *ctor;
6849 void *unboxed, *params [2];
6852 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6854 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6857 params [1] = typedarg;
6858 retval = mono_object_new (mono_domain_get (), klass);
6859 unboxed = mono_object_unbox (retval);
6860 mono_runtime_invoke (ctor, unboxed, params, NULL);
6866 type_is_reference (MonoType *type)
6868 switch (type->type) {
6869 case MONO_TYPE_BOOLEAN:
6870 case MONO_TYPE_CHAR:
6883 case MONO_TYPE_VALUETYPE:
6891 free_param_data (MonoMethodSignature *sig, void **params) {
6893 for (i = 0; i < sig->param_count; ++i) {
6894 if (!type_is_reference (sig->params [i]))
6895 g_free (params [i]);
6900 * Find the field index in the metadata FieldDef table.
6903 find_field_index (MonoClass *klass, MonoClassField *field) {
6906 for (i = 0; i < klass->field.count; ++i) {
6907 if (field == &klass->fields [i])
6908 return klass->field.first + 1 + i;
6914 * Find the property index in the metadata Property table.
6917 find_property_index (MonoClass *klass, MonoProperty *property) {
6920 for (i = 0; i < klass->property.count; ++i) {
6921 if (property == &klass->properties [i])
6922 return klass->property.first + 1 + i;
6928 * Find the event index in the metadata Event table.
6931 find_event_index (MonoClass *klass, MonoEvent *event) {
6934 for (i = 0; i < klass->event.count; ++i) {
6935 if (event == &klass->events [i])
6936 return klass->event.first + 1 + i;
6942 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
6944 const char *p = (const char*)data;
6946 guint32 i, j, num_named;
6950 mono_class_init (method->klass);
6953 attr = mono_object_new (mono_domain_get (), method->klass);
6954 mono_runtime_invoke (method, attr, NULL, NULL);
6958 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6961 /*g_print ("got attr %s\n", method->klass->name);*/
6963 /* Allocate using alloca so it gets GC tracking */
6964 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6968 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6969 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6973 attr = mono_object_new (mono_domain_get (), method->klass);
6974 mono_runtime_invoke (method, attr, params, NULL);
6975 free_param_data (method->signature, params);
6976 num_named = read16 (named);
6978 for (j = 0; j < num_named; j++) {
6980 gboolean is_boxed = FALSE;
6981 char *name, named_type, data_type;
6982 named_type = *named++;
6983 data_type = *named++; /* type of data */
6984 if (data_type == 0x51)
6987 if (data_type == 0x55) {
6990 type_len = mono_metadata_decode_blob_size (named, &named);
6991 type_name = g_malloc (type_len + 1);
6992 memcpy (type_name, named, type_len);
6993 type_name [type_len] = 0;
6995 /* FIXME: lookup the type and check type consistency */
6997 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6998 /* this seems to be the type of the element of the array */
6999 /* g_print ("skipping 0x%02x after prop\n", *named); */
7002 name_len = mono_metadata_decode_blob_size (named, &named);
7003 name = g_malloc (name_len + 1);
7004 memcpy (name, named, name_len);
7005 name [name_len] = 0;
7007 if (named_type == 0x53) {
7008 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7009 void *val = load_cattr_value (image, field->type, named, &named);
7010 mono_field_set_value (attr, field, val);
7011 if (!type_is_reference (field->type))
7013 } else if (named_type == 0x54) {
7016 MonoType *prop_type;
7018 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7019 /* can we have more that 1 arg in a custom attr named property? */
7020 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7021 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7022 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7023 mono_property_set_value (prop, attr, pparams, NULL);
7024 if (!type_is_reference (prop_type))
7025 g_free (pparams [0]);
7034 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7036 MonoArray *typedargs, *namedargs;
7037 MonoClass *attrklass;
7038 static MonoClass *klass;
7039 static MonoMethod *ctor;
7042 const char *p = (const char*)data;
7044 guint32 i, j, num_named;
7047 mono_class_init (method->klass);
7050 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7052 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
7054 domain = mono_domain_get ();
7056 /* This is for Attributes with no parameters */
7057 attr = mono_object_new (domain, klass);
7058 params [0] = mono_method_get_object (domain, method, NULL);
7059 params [1] = params [2] = NULL;
7060 mono_runtime_invoke (method, attr, params, NULL);
7064 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7067 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7071 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7072 MonoObject *obj, *typedarg;
7075 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7076 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7077 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7078 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7079 mono_array_setref (typedargs, i, typedarg);
7081 if (!type_is_reference (mono_method_signature (method)->params [i]))
7086 num_named = read16 (named);
7087 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7089 attrklass = method->klass;
7090 for (j = 0; j < num_named; j++) {
7092 char *name, named_type, data_type;
7093 named_type = *named++;
7094 data_type = *named++; /* type of data */
7095 if (data_type == 0x55) {
7098 type_len = mono_metadata_decode_blob_size (named, &named);
7099 type_name = g_malloc (type_len + 1);
7100 memcpy (type_name, named, type_len);
7101 type_name [type_len] = 0;
7103 /* FIXME: lookup the type and check type consistency */
7105 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
7106 /* this seems to be the type of the element of the array */
7107 /* g_print ("skipping 0x%02x after prop\n", *named); */
7110 name_len = mono_metadata_decode_blob_size (named, &named);
7111 name = g_malloc (name_len + 1);
7112 memcpy (name, named, name_len);
7113 name [name_len] = 0;
7115 if (named_type == 0x53) {
7116 MonoObject *obj, *typedarg, *namedarg;
7117 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7118 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7120 minfo = mono_field_get_object (domain, NULL, field);
7121 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7122 typedarg = create_cattr_typed_arg (field->type, obj);
7123 namedarg = create_cattr_named_arg (minfo, typedarg);
7124 mono_array_setref (namedargs, j, namedarg);
7125 if (!type_is_reference (field->type))
7127 } else if (named_type == 0x54) {
7128 MonoObject *obj, *typedarg, *namedarg;
7129 MonoType *prop_type;
7131 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7133 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7134 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7135 minfo = mono_property_get_object (domain, NULL, prop);
7136 val = load_cattr_value (image, prop_type, named, &named);
7137 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7138 typedarg = create_cattr_typed_arg (prop_type, obj);
7139 namedarg = create_cattr_named_arg (minfo, typedarg);
7140 mono_array_setref (namedargs, j, namedarg);
7141 if (!type_is_reference (prop_type))
7146 attr = mono_object_new (domain, klass);
7147 params [0] = mono_method_get_object (domain, method, NULL);
7148 params [1] = typedargs;
7149 params [2] = namedargs;
7150 mono_runtime_invoke (ctor, attr, params, NULL);
7155 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7162 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7163 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7164 for (i = 0; i < cinfo->num_attrs; ++i) {
7165 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7166 mono_array_setref (result, i, attr);
7172 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7180 for (i = 0; i < cinfo->num_attrs; ++i) {
7181 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7185 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7186 result = mono_array_new (mono_domain_get (), klass, n);
7188 for (i = 0; i < cinfo->num_attrs; ++i) {
7189 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7190 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7191 mono_array_setref (result, n, attr);
7199 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7202 static MonoClass *klass;
7207 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7209 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7210 for (i = 0; i < cinfo->num_attrs; ++i) {
7211 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7212 mono_array_setref (result, i, attr);
7218 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7220 guint32 mtoken, i, len;
7221 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7223 MonoCustomAttrInfo *ainfo;
7224 GList *tmp, *list = NULL;
7227 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7229 i = mono_metadata_custom_attrs_from_index (image, idx);
7233 while (i < ca->rows) {
7234 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7236 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7239 len = g_list_length (list);
7242 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7243 ainfo->num_attrs = len;
7244 ainfo->image = image;
7245 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7246 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7247 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7248 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7249 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7250 mtoken |= MONO_TOKEN_METHOD_DEF;
7252 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7253 mtoken |= MONO_TOKEN_MEMBER_REF;
7256 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7259 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7260 if (!ainfo->attrs [i].ctor)
7261 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7262 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7263 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7264 ainfo->attrs [i].data = (guchar*)data;
7272 mono_custom_attrs_from_method (MonoMethod *method)
7274 MonoCustomAttrInfo *cinfo;
7277 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7279 idx = mono_method_get_index (method);
7280 idx <<= MONO_CUSTOM_ATTR_BITS;
7281 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7282 return mono_custom_attrs_from_index (method->klass->image, idx);
7286 mono_custom_attrs_from_class (MonoClass *klass)
7288 MonoCustomAttrInfo *cinfo;
7291 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7293 idx = mono_metadata_token_index (klass->type_token);
7294 idx <<= MONO_CUSTOM_ATTR_BITS;
7295 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7296 return mono_custom_attrs_from_index (klass->image, idx);
7300 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7302 MonoCustomAttrInfo *cinfo;
7305 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7307 idx = 1; /* there is only one assembly */
7308 idx <<= MONO_CUSTOM_ATTR_BITS;
7309 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7310 return mono_custom_attrs_from_index (assembly->image, idx);
7313 static MonoCustomAttrInfo*
7314 mono_custom_attrs_from_module (MonoImage *image)
7316 MonoCustomAttrInfo *cinfo;
7319 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7321 idx = 1; /* there is only one module */
7322 idx <<= MONO_CUSTOM_ATTR_BITS;
7323 idx |= MONO_CUSTOM_ATTR_MODULE;
7324 return mono_custom_attrs_from_index (image, idx);
7328 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7330 MonoCustomAttrInfo *cinfo;
7333 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7335 idx = find_property_index (klass, property);
7336 idx <<= MONO_CUSTOM_ATTR_BITS;
7337 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7338 return mono_custom_attrs_from_index (klass->image, idx);
7342 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7344 MonoCustomAttrInfo *cinfo;
7347 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7349 idx = find_event_index (klass, event);
7350 idx <<= MONO_CUSTOM_ATTR_BITS;
7351 idx |= MONO_CUSTOM_ATTR_EVENT;
7352 return mono_custom_attrs_from_index (klass->image, idx);
7356 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7358 MonoCustomAttrInfo *cinfo;
7361 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7363 idx = find_field_index (klass, field);
7364 idx <<= MONO_CUSTOM_ATTR_BITS;
7365 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7366 return mono_custom_attrs_from_index (klass->image, idx);
7370 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7373 guint32 i, idx, method_index;
7374 guint32 param_list, param_last, param_pos, found;
7376 MonoReflectionMethodAux *aux;
7378 if (method->klass->image->dynamic) {
7379 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7380 if (!aux || !aux->param_cattr)
7382 return aux->param_cattr [param];
7385 image = method->klass->image;
7386 method_index = mono_method_get_index (method);
7387 ca = &image->tables [MONO_TABLE_METHOD];
7389 if (method->klass->generic_class || mono_method_signature (method)->generic_param_count) {
7390 /* FIXME FIXME FIXME */
7394 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7395 if (method_index == ca->rows) {
7396 ca = &image->tables [MONO_TABLE_PARAM];
7397 param_last = ca->rows + 1;
7399 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7400 ca = &image->tables [MONO_TABLE_PARAM];
7403 for (i = param_list; i < param_last; ++i) {
7404 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7405 if (param_pos == param) {
7413 idx <<= MONO_CUSTOM_ATTR_BITS;
7414 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7415 return mono_custom_attrs_from_index (image, idx);
7419 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7423 for (i = 0; i < ainfo->num_attrs; ++i) {
7424 klass = ainfo->attrs [i].ctor->klass;
7425 if (mono_class_has_parent (klass, attr_klass))
7432 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7439 for (i = 0; i < ainfo->num_attrs; ++i) {
7440 klass = ainfo->attrs [i].ctor->klass;
7441 if (mono_class_has_parent (klass, attr_klass)) {
7446 if (attr_index == -1)
7449 attrs = mono_custom_attrs_construct (ainfo);
7451 return mono_array_get (attrs, MonoObject*, attr_index);
7457 * mono_reflection_get_custom_attrs_info:
7458 * @obj: a reflection object handle
7460 * Return the custom attribute info for attributes defined for the
7461 * reflection handle @obj. The objects.
7464 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7467 MonoCustomAttrInfo *cinfo = NULL;
7469 klass = obj->vtable->klass;
7470 if (klass == mono_defaults.monotype_class) {
7471 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7472 klass = mono_class_from_mono_type (rtype->type);
7473 cinfo = mono_custom_attrs_from_class (klass);
7474 } else if (strcmp ("Assembly", klass->name) == 0) {
7475 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7476 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7477 } else if (strcmp ("Module", klass->name) == 0) {
7478 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7479 cinfo = mono_custom_attrs_from_module (module->image);
7480 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7481 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7482 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7483 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7484 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7485 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7486 } else if (strcmp ("MonoField", klass->name) == 0) {
7487 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7488 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7489 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7490 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7491 cinfo = mono_custom_attrs_from_method (rmethod->method);
7492 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7493 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7494 cinfo = mono_custom_attrs_from_method (method);
7495 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7496 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7497 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7498 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7499 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7500 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7501 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7502 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7503 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7504 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7505 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7506 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7507 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7508 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7509 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7510 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7511 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7512 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7513 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7514 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7515 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7516 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7517 } else { /* handle other types here... */
7518 g_error ("get custom attrs not yet supported for %s", klass->name);
7525 * mono_reflection_get_custom_attrs_by_type:
7526 * @obj: a reflection object handle
7528 * Return an array with all the custom attributes defined of the
7529 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7530 * of that type are returned. The objects are fully build.
7533 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7536 MonoCustomAttrInfo *cinfo;
7538 cinfo = mono_reflection_get_custom_attrs_info (obj);
7541 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7543 result = mono_custom_attrs_construct (cinfo);
7545 mono_custom_attrs_free (cinfo);
7548 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7549 result = mono_array_new (mono_domain_get (), klass, 0);
7556 * mono_reflection_get_custom_attrs:
7557 * @obj: a reflection object handle
7559 * Return an array with all the custom attributes defined of the
7560 * reflection handle @obj. The objects are fully build.
7563 mono_reflection_get_custom_attrs (MonoObject *obj)
7565 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7569 * mono_reflection_get_custom_attrs_data:
7570 * @obj: a reflection obj handle
7572 * Returns an array of System.Reflection.CustomAttributeData,
7573 * which include information about attributes reflected on
7574 * types loaded using the Reflection Only methods
7577 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7580 MonoCustomAttrInfo *cinfo;
7582 cinfo = mono_reflection_get_custom_attrs_info (obj);
7584 result = mono_custom_attrs_data_construct (cinfo);
7586 mono_custom_attrs_free (cinfo);
7589 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7590 result = mono_array_new (mono_domain_get (), klass, 0);
7597 * LOCKING: Assumes the loader lock is held.
7599 static MonoMethodSignature*
7600 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7601 MonoMethodSignature *sig;
7604 count = parameters? mono_array_length (parameters): 0;
7606 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7607 sig->param_count = count;
7608 sig->sentinelpos = -1; /* FIXME */
7609 for (i = 0; i < count; ++i) {
7610 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7611 sig->params [i] = pt->type;
7617 * LOCKING: Assumes the loader lock is held.
7619 static MonoMethodSignature*
7620 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7621 MonoMethodSignature *sig;
7623 sig = parameters_to_signature (mp, ctor->parameters);
7624 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7625 sig->ret = &mono_defaults.void_class->byval_arg;
7630 * LOCKING: Assumes the loader lock is held.
7632 static MonoMethodSignature*
7633 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7634 MonoMethodSignature *sig;
7636 sig = parameters_to_signature (mp, method->parameters);
7637 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7638 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7639 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7643 static MonoMethodSignature*
7644 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7645 MonoMethodSignature *sig;
7647 sig = parameters_to_signature (NULL, method->parameters);
7648 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7649 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7650 sig->generic_param_count = 0;
7655 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7657 MonoClass *klass = mono_object_class (prop);
7658 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7659 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7660 *name = mono_string_to_utf8 (pb->name);
7661 *type = pb->type->type;
7663 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7664 *name = g_strdup (p->property->name);
7665 if (p->property->get)
7666 *type = mono_method_signature (p->property->get)->ret;
7668 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7673 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7675 MonoClass *klass = mono_object_class (field);
7676 if (strcmp (klass->name, "FieldBuilder") == 0) {
7677 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7678 *name = mono_string_to_utf8 (fb->name);
7679 *type = fb->type->type;
7681 MonoReflectionField *f = (MonoReflectionField *)field;
7682 *name = g_strdup (f->field->name);
7683 *type = f->field->type;
7688 * Encode a value in a custom attribute stream of bytes.
7689 * The value to encode is either supplied as an object in argument val
7690 * (valuetypes are boxed), or as a pointer to the data in the
7692 * @type represents the type of the value
7693 * @buffer is the start of the buffer
7694 * @p the current position in the buffer
7695 * @buflen contains the size of the buffer and is used to return the new buffer size
7696 * if this needs to be realloced.
7697 * @retbuffer and @retp return the start and the position of the buffer
7700 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7702 MonoTypeEnum simple_type;
7704 if ((p-buffer) + 10 >= *buflen) {
7707 newbuf = g_realloc (buffer, *buflen);
7708 p = newbuf + (p-buffer);
7712 argval = ((char*)arg + sizeof (MonoObject));
7713 simple_type = type->type;
7715 switch (simple_type) {
7716 case MONO_TYPE_BOOLEAN:
7721 case MONO_TYPE_CHAR:
7724 swap_with_size (p, argval, 2, 1);
7730 swap_with_size (p, argval, 4, 1);
7736 swap_with_size (p, argval, 8, 1);
7739 case MONO_TYPE_VALUETYPE:
7740 if (type->data.klass->enumtype) {
7741 simple_type = type->data.klass->enum_basetype->type;
7744 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7747 case MONO_TYPE_STRING: {
7754 str = mono_string_to_utf8 ((MonoString*)arg);
7755 slen = strlen (str);
7756 if ((p-buffer) + 10 + slen >= *buflen) {
7760 newbuf = g_realloc (buffer, *buflen);
7761 p = newbuf + (p-buffer);
7764 mono_metadata_encode_value (slen, p, &p);
7765 memcpy (p, str, slen);
7770 case MONO_TYPE_CLASS: {
7778 k = mono_object_class (arg);
7779 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7780 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7781 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7783 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7784 slen = strlen (str);
7785 if ((p-buffer) + 10 + slen >= *buflen) {
7789 newbuf = g_realloc (buffer, *buflen);
7790 p = newbuf + (p-buffer);
7793 mono_metadata_encode_value (slen, p, &p);
7794 memcpy (p, str, slen);
7799 case MONO_TYPE_SZARRAY: {
7801 MonoClass *eclass, *arg_eclass;
7804 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7807 len = mono_array_length ((MonoArray*)arg);
7809 *p++ = (len >> 8) & 0xff;
7810 *p++ = (len >> 16) & 0xff;
7811 *p++ = (len >> 24) & 0xff;
7813 *retbuffer = buffer;
7814 eclass = type->data.klass;
7815 arg_eclass = mono_object_class (arg)->element_class;
7818 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7819 eclass = mono_defaults.object_class;
7821 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7822 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7823 int elsize = mono_class_array_element_size (arg_eclass);
7824 for (i = 0; i < len; ++i) {
7825 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7828 } else if (eclass->valuetype && arg_eclass->valuetype) {
7829 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7830 int elsize = mono_class_array_element_size (eclass);
7831 for (i = 0; i < len; ++i) {
7832 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7836 for (i = 0; i < len; ++i) {
7837 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7842 case MONO_TYPE_OBJECT: {
7848 * The parameter type is 'object' but the type of the actual
7849 * argument is not. So we have to add type information to the blob
7850 * too. This is completely undocumented in the spec.
7854 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7859 klass = mono_object_class (arg);
7861 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7864 } else if (klass->enumtype) {
7866 } else if (klass == mono_defaults.string_class) {
7867 simple_type = MONO_TYPE_STRING;
7870 } else if (klass->rank == 1) {
7871 simple_type = MONO_TYPE_SZARRAY;
7873 *p++ = klass->element_class->byval_arg.type;
7875 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7876 *p++ = simple_type = klass->byval_arg.type;
7879 g_error ("unhandled type in custom attr");
7881 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7882 slen = strlen (str);
7883 if ((p-buffer) + 10 + slen >= *buflen) {
7887 newbuf = g_realloc (buffer, *buflen);
7888 p = newbuf + (p-buffer);
7891 mono_metadata_encode_value (slen, p, &p);
7892 memcpy (p, str, slen);
7895 simple_type = klass->enum_basetype->type;
7899 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7902 *retbuffer = buffer;
7906 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7909 /* Preallocate a large enough buffer */
7910 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7911 char *str = type_get_qualified_name (type, NULL);
7917 len += strlen (name);
7919 if ((p-buffer) + 20 + len >= *buflen) {
7923 newbuf = g_realloc (buffer, *buflen);
7924 p = newbuf + (p-buffer);
7928 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7929 char *str = type_get_qualified_name (type, NULL);
7930 int slen = strlen (str);
7934 * This seems to be optional...
7937 mono_metadata_encode_value (slen, p, &p);
7938 memcpy (p, str, slen);
7941 } else if (type->type == MONO_TYPE_OBJECT) {
7943 } else if (type->type == MONO_TYPE_CLASS) {
7944 /* it should be a type: encode_cattr_value () has the check */
7947 mono_metadata_encode_value (type->type, p, &p);
7948 if (type->type == MONO_TYPE_SZARRAY)
7949 mono_metadata_encode_value (type->data.klass->this_arg.type, p, &p);
7951 len = strlen (name);
7952 mono_metadata_encode_value (len, p, &p);
7953 memcpy (p, name, len);
7955 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7957 *retbuffer = buffer;
7961 * mono_reflection_get_custom_attrs_blob:
7962 * @ctor: custom attribute constructor
7963 * @ctorArgs: arguments o the constructor
7969 * Creates the blob of data that needs to be saved in the metadata and that represents
7970 * the custom attributed described by @ctor, @ctorArgs etc.
7971 * Returns: a Byte array representing the blob of data.
7974 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7977 MonoMethodSignature *sig;
7982 MONO_ARCH_SAVE_REGS;
7984 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7985 /* sig is freed later so allocate it in the heap */
7986 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
7988 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7991 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7993 p = buffer = g_malloc (buflen);
7994 /* write the prolog */
7997 for (i = 0; i < sig->param_count; ++i) {
7998 arg = mono_array_get (ctorArgs, MonoObject*, i);
7999 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8003 i += mono_array_length (properties);
8005 i += mono_array_length (fields);
8007 *p++ = (i >> 8) & 0xff;
8010 for (i = 0; i < mono_array_length (properties); ++i) {
8014 prop = mono_array_get (properties, gpointer, i);
8015 get_prop_name_and_type (prop, &pname, &ptype);
8016 *p++ = 0x54; /* PROPERTY signature */
8017 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8024 for (i = 0; i < mono_array_length (fields); ++i) {
8028 field = mono_array_get (fields, gpointer, i);
8029 get_field_name_and_type (field, &fname, &ftype);
8030 *p++ = 0x53; /* FIELD signature */
8031 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8036 g_assert (p - buffer <= buflen);
8037 buflen = p - buffer;
8038 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8039 p = mono_array_addr (result, char, 0);
8040 memcpy (p, buffer, buflen);
8042 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8048 static void* reflection_info_desc = NULL;
8052 * mono_reflection_setup_internal_class:
8053 * @tb: a TypeBuilder object
8055 * Creates a MonoClass that represents the TypeBuilder.
8056 * This is a trick that lets us simplify a lot of reflection code
8057 * (and will allow us to support Build and Run assemblies easier).
8060 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8062 MonoClass *klass, *parent;
8064 MONO_ARCH_SAVE_REGS;
8066 mono_loader_lock ();
8069 /* check so we can compile corlib correctly */
8070 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8071 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8072 parent = tb->parent->type->data.klass;
8074 parent = my_mono_class_from_mono_type (tb->parent->type);
8080 /* the type has already being created: it means we just have to change the parent */
8081 if (tb->type.type) {
8082 klass = mono_class_from_mono_type (tb->type.type);
8083 klass->parent = NULL;
8084 /* fool mono_class_setup_parent */
8085 klass->supertypes = NULL;
8086 mono_class_setup_parent (klass, parent);
8087 mono_class_setup_mono_type (klass);
8088 mono_loader_unlock ();
8092 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8094 klass->image = &tb->module->dynamic_image->image;
8096 klass->inited = 1; /* we lie to the runtime */
8097 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8098 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8099 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8100 klass->flags = tb->attrs;
8102 klass->element_class = klass;
8105 if (!reflection_info_desc) {
8107 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);
8109 mono_gc_register_root (&klass->reflection_info, sizeof (gpointer), reflection_info_desc);
8111 klass->reflection_info = tb;
8113 /* Put into cache so mono_class_get () will find it */
8114 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8116 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8117 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8119 if (parent != NULL) {
8120 mono_class_setup_parent (klass, parent);
8121 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8122 const char *old_n = klass->name;
8123 /* trick to get relative numbering right when compiling corlib */
8124 klass->name = "BuildingObject";
8125 mono_class_setup_parent (klass, mono_defaults.object_class);
8126 klass->name = old_n;
8129 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8130 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8131 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8132 klass->instance_size = sizeof (MonoObject);
8133 klass->size_inited = 1;
8134 mono_class_setup_vtable_general (klass, NULL, 0);
8137 mono_class_setup_mono_type (klass);
8139 mono_class_setup_supertypes (klass);
8142 * FIXME: handle interfaces.
8145 tb->type.type = &klass->byval_arg;
8147 if (tb->nesting_type) {
8148 g_assert (tb->nesting_type->type);
8149 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8152 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8154 mono_loader_unlock ();
8158 * mono_reflection_setup_generic_class:
8159 * @tb: a TypeBuilder object
8161 * Setup the generic class before adding the first generic parameter.
8164 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8168 MONO_ARCH_SAVE_REGS;
8170 klass = my_mono_class_from_mono_type (tb->type.type);
8171 if (tb->generic_container)
8174 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8175 tb->generic_container->klass = klass;
8177 tb->generic_container->context.container = tb->generic_container;
8181 * mono_reflection_create_generic_class:
8182 * @tb: a TypeBuilder object
8184 * Creates the generic class after all generic parameters have been added.
8187 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8192 MONO_ARCH_SAVE_REGS;
8194 klass = my_mono_class_from_mono_type (tb->type.type);
8196 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8198 if (klass->generic_container || (count == 0))
8201 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
8203 klass->generic_container = tb->generic_container;
8205 klass->generic_container->type_argc = count;
8206 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8208 for (i = 0; i < count; i++) {
8209 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8210 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8211 g_assert (klass->generic_container->type_params [i].owner);
8214 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
8218 * mono_reflection_create_internal_class:
8219 * @tb: a TypeBuilder object
8221 * Actually create the MonoClass that is associated with the TypeBuilder.
8224 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8228 MONO_ARCH_SAVE_REGS;
8230 klass = my_mono_class_from_mono_type (tb->type.type);
8232 mono_loader_lock ();
8233 if (klass->enumtype && klass->enum_basetype == NULL) {
8234 MonoReflectionFieldBuilder *fb;
8237 g_assert (tb->fields != NULL);
8238 g_assert (mono_array_length (tb->fields) >= 1);
8240 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8242 klass->enum_basetype = fb->type->type;
8243 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8244 if (!klass->element_class)
8245 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8248 * get the element_class from the current corlib.
8250 ec = default_class_from_mono_type (klass->enum_basetype);
8251 klass->instance_size = ec->instance_size;
8252 klass->size_inited = 1;
8254 * this is almost safe to do with enums and it's needed to be able
8255 * to create objects of the enum type (for use in SetConstant).
8257 /* FIXME: Does this mean enums can't have method overrides ? */
8258 mono_class_setup_vtable_general (klass, NULL, 0);
8260 mono_loader_unlock ();
8263 static MonoMarshalSpec*
8264 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8265 MonoReflectionMarshal *minfo)
8267 MonoMarshalSpec *res;
8269 res = g_new0 (MonoMarshalSpec, 1);
8270 res->native = minfo->type;
8272 switch (minfo->type) {
8273 case MONO_NATIVE_LPARRAY:
8274 res->data.array_data.elem_type = minfo->eltype;
8275 if (minfo->has_size) {
8276 res->data.array_data.param_num = minfo->param_num;
8277 res->data.array_data.num_elem = minfo->count;
8278 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8281 res->data.array_data.param_num = -1;
8282 res->data.array_data.num_elem = -1;
8283 res->data.array_data.elem_mult = -1;
8287 case MONO_NATIVE_BYVALTSTR:
8288 case MONO_NATIVE_BYVALARRAY:
8289 res->data.array_data.num_elem = minfo->count;
8292 case MONO_NATIVE_CUSTOM:
8293 if (minfo->marshaltyperef)
8294 res->data.custom_data.custom_name =
8295 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8297 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8307 MonoReflectionMarshal*
8308 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8309 MonoMarshalSpec *spec)
8311 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8312 MonoReflectionMarshal *minfo;
8315 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8316 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8317 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8318 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8321 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8322 minfo->type = spec->native;
8324 switch (minfo->type) {
8325 case MONO_NATIVE_LPARRAY:
8326 minfo->eltype = spec->data.array_data.elem_type;
8327 minfo->count = spec->data.array_data.num_elem;
8328 minfo->param_num = spec->data.array_data.param_num;
8331 case MONO_NATIVE_BYVALTSTR:
8332 case MONO_NATIVE_BYVALARRAY:
8333 minfo->count = spec->data.array_data.num_elem;
8336 case MONO_NATIVE_CUSTOM:
8337 if (spec->data.custom_data.custom_name) {
8338 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8340 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8342 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8344 if (spec->data.custom_data.cookie)
8345 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8356 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8357 ReflectionMethodBuilder *rmb,
8358 MonoMethodSignature *sig)
8361 MonoMethodNormal *pm;
8362 MonoMarshalSpec **specs;
8363 MonoReflectionMethodAux *method_aux;
8368 g_assert (!klass->generic_class);
8371 * Methods created using a MethodBuilder should have their memory allocated
8372 * inside the image mempool, while dynamic methods should have their memory
8375 dynamic = rmb->refs != NULL;
8376 mp = dynamic ? NULL : klass->image->mempool;
8378 mono_loader_lock ();
8380 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8381 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8382 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8384 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8386 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8388 pm = (MonoMethodNormal*)m;
8391 m->flags = rmb->attrs;
8392 m->iflags = rmb->iattrs;
8393 m->name = dynamic ? mono_string_to_utf8 (rmb->name) : mono_string_to_utf8_mp (mp, rmb->name);
8396 m->skip_visibility = rmb->skip_visibility;
8398 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8400 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8401 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8404 m->signature->pinvoke = 1;
8405 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8406 m->signature->pinvoke = 1;
8408 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8410 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8411 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8413 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8415 if (klass->image->dynamic)
8416 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8418 mono_loader_unlock ();
8421 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8422 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8423 MonoMethodHeader *header;
8425 gint32 max_stack, i;
8426 gint32 num_locals = 0;
8427 gint32 num_clauses = 0;
8431 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8432 code_size = rmb->ilgen->code_len;
8433 max_stack = rmb->ilgen->max_stack;
8434 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8435 if (rmb->ilgen->ex_handlers)
8436 num_clauses = method_count_clauses (rmb->ilgen);
8439 code = mono_array_addr (rmb->code, guint8, 0);
8440 code_size = mono_array_length (rmb->code);
8441 /* we probably need to run a verifier on the code... */
8451 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8452 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8453 header->code_size = code_size;
8454 header->code = mp_g_malloc (mp, code_size);
8455 memcpy ((char*)header->code, code, code_size);
8456 header->max_stack = max_stack;
8457 header->init_locals = rmb->init_locals;
8458 header->num_locals = num_locals;
8460 for (i = 0; i < num_locals; ++i) {
8461 MonoReflectionLocalBuilder *lb =
8462 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8464 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8465 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8468 header->num_clauses = num_clauses;
8470 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8471 rmb->ilgen, num_clauses);
8474 pm->header = header;
8477 if (rmb->generic_params) {
8478 int count = mono_array_length (rmb->generic_params);
8479 MonoGenericContainer *container;
8480 MonoGenericContext *context;
8482 m->generic_container = container = rmb->generic_container;
8483 container->type_argc = count;
8484 container->type_params = g_new0 (MonoGenericParam, count);
8486 for (i = 0; i < count; i++) {
8487 MonoReflectionGenericParam *gp =
8488 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8490 container->type_params [i] = *gp->type.type->data.generic_param;
8491 container->type_params [i].method = m;
8494 context = &container->context;
8495 context->container = container;
8496 if (klass->generic_container) {
8497 container->parent = klass->generic_container;
8498 context->gclass = klass->generic_container->context.gclass;
8500 context->gmethod = mono_get_shared_generic_method (container);
8504 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8508 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8510 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8511 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8512 for (i = 0; i < rmb->nrefs; ++i)
8513 data [i + 1] = rmb->refs [i];
8518 /* Parameter info */
8521 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8522 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8523 for (i = 0; i <= m->signature->param_count; ++i) {
8524 MonoReflectionParamBuilder *pb;
8525 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8526 if ((i > 0) && (pb->attrs)) {
8527 /* Make a copy since it might point to a shared type structure */
8528 /* FIXME: Alloc this from a mempool */
8529 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)));
8530 m->signature->params [i - 1]->attrs = pb->attrs;
8533 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8534 MonoDynamicImage *assembly;
8535 guint32 idx, def_type, len;
8539 if (!method_aux->param_defaults) {
8540 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8541 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8543 assembly = (MonoDynamicImage*)klass->image;
8544 idx = encode_constant (assembly, pb->def_value, &def_type);
8545 /* Copy the data from the blob since it might get realloc-ed */
8546 p = assembly->blob.data + idx;
8547 len = mono_metadata_decode_blob_size (p, &p2);
8549 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8550 method_aux->param_default_types [i] = def_type;
8551 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8555 method_aux->param_names [i] = dynamic ? mono_string_to_utf8 (pb->name) : mono_string_to_utf8_mp (mp, pb->name);
8557 if (!method_aux->param_cattr)
8558 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8559 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8565 /* Parameter marshalling */
8568 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8569 MonoReflectionParamBuilder *pb;
8570 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8571 if (pb->marshal_info) {
8573 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8574 specs [pb->position] =
8575 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8579 if (specs != NULL) {
8581 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8582 method_aux->param_marshall = specs;
8585 if (klass->image->dynamic && method_aux)
8586 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8588 mono_loader_unlock ();
8594 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8596 ReflectionMethodBuilder rmb;
8597 MonoMethodSignature *sig;
8599 mono_loader_lock ();
8600 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8601 mono_loader_unlock ();
8603 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8605 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8606 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8608 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8609 /* ilgen is no longer needed */
8617 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8619 ReflectionMethodBuilder rmb;
8620 MonoMethodSignature *sig;
8622 mono_loader_lock ();
8623 sig = method_builder_to_signature (klass->image->mempool, mb);
8624 mono_loader_unlock ();
8626 reflection_methodbuilder_from_method_builder (&rmb, mb);
8628 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8629 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8631 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8632 /* ilgen is no longer needed */
8638 static MonoClassField*
8639 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8641 MonoClassField *field;
8645 field = g_new0 (MonoClassField, 1);
8647 field->name = mono_string_to_utf8 (fb->name);
8649 /* FIXME: handle type modifiers */
8650 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8651 field->type->attrs = fb->attrs;
8653 field->type = fb->type->type;
8655 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8656 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8657 if (fb->offset != -1)
8658 field->offset = fb->offset;
8659 field->parent = klass;
8660 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8662 if (fb->def_value) {
8663 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8664 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8665 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8666 /* Copy the data from the blob since it might get realloc-ed */
8667 p = assembly->blob.data + idx;
8668 len = mono_metadata_decode_blob_size (p, &p2);
8670 field->data = g_malloc (len);
8671 memcpy ((gpointer)field->data, p, len);
8678 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8681 MonoReflectionTypeBuilder *tb = NULL;
8682 MonoGenericClass *gclass, *cached;
8683 MonoInflatedGenericClass *igclass;
8684 MonoDynamicGenericClass *dgclass = NULL;
8685 gboolean is_dynamic = FALSE;
8690 klass = mono_class_from_mono_type (type->type);
8691 if (!klass->generic_container && !klass->generic_class &&
8692 !(klass->nested_in && klass->nested_in->generic_container))
8695 mono_loader_lock ();
8697 domain = mono_object_domain (type);
8699 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8700 tb = (MonoReflectionTypeBuilder *) type;
8703 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8704 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8705 MonoReflectionType *rgt = rgi->generic_type;
8707 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8708 tb = (MonoReflectionTypeBuilder *) rgt;
8711 } else if (klass->wastypebuilder) {
8712 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8718 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8719 igclass = &dgclass->generic_class;
8720 gclass = &igclass->generic_class;
8721 gclass->is_dynamic = TRUE;
8722 gclass->is_inflated = TRUE;
8724 igclass = g_new0 (MonoInflatedGenericClass, 1);
8725 gclass = &igclass->generic_class;
8726 gclass->is_inflated = TRUE;
8729 gclass->inst = g_new0 (MonoGenericInst, 1);
8731 gclass->inst->type_argc = type_argc;
8732 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8733 gclass->inst->is_reference = 1;
8735 for (i = 0; i < gclass->inst->type_argc; ++i) {
8736 MonoType *t = dup_type (types [i]);
8738 if (!gclass->inst->is_open)
8739 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8740 if (gclass->inst->is_reference)
8741 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8742 gclass->inst->type_argv [i] = t;
8745 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8747 gclass->container_class = klass;
8749 if (klass->generic_class) {
8750 MonoGenericClass *kgclass = klass->generic_class;
8751 MonoGenericClass *ogclass = gclass;
8753 ogclass->context = g_new0 (MonoGenericContext, 1);
8754 ogclass->context->container = gclass->container_class->generic_container;
8755 ogclass->context->gclass = gclass;
8758 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8759 igclass = &dgclass->generic_class;
8760 gclass = &igclass->generic_class;
8761 gclass->is_dynamic = TRUE;
8762 gclass->is_inflated = TRUE;
8764 igclass = g_new0 (MonoInflatedGenericClass, 1);
8765 gclass = &igclass->generic_class;
8766 gclass->is_inflated = TRUE;
8769 gclass->inst = g_new0 (MonoGenericInst, 1);
8771 gclass->inst->type_argc = kgclass->inst->type_argc;
8772 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8773 gclass->inst->is_reference = 1;
8775 for (i = 0; i < gclass->inst->type_argc; i++) {
8776 MonoType *t = kgclass->inst->type_argv [i];
8778 t = mono_class_inflate_generic_type (t, ogclass->context);
8780 if (!gclass->inst->is_open)
8781 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8782 if (gclass->inst->is_reference)
8783 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8785 gclass->inst->type_argv [i] = t;
8788 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8790 gclass->container_class = kgclass->container_class;
8793 geninst = g_new0 (MonoType, 1);
8794 geninst->type = MONO_TYPE_GENERICINST;
8796 cached = mono_metadata_lookup_generic_class (gclass);
8799 mono_loader_unlock ();
8800 geninst->data.generic_class = cached;
8804 geninst->data.generic_class = gclass;
8806 gclass->context = g_new0 (MonoGenericContext, 1);
8807 gclass->context->container = gclass->container_class->generic_container;
8808 gclass->context->gclass = gclass;
8810 mono_loader_unlock ();
8816 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8819 MonoGenericClass *gclass, *cached;
8820 MonoInflatedGenericClass *igclass;
8824 klass = mono_class_from_mono_type (type);
8825 if (!klass->generic_container && !klass->generic_class &&
8826 !(klass->nested_in && klass->nested_in->generic_container))
8829 mono_loader_lock ();
8831 igclass = g_new0 (MonoInflatedGenericClass, 1);
8832 gclass = &igclass->generic_class;
8833 gclass->is_inflated = TRUE;
8835 gclass->inst = g_new0 (MonoGenericInst, 1);
8836 gclass->inst->type_argc = type_argc;
8837 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8838 gclass->inst->is_reference = 1;
8840 for (i = 0; i < gclass->inst->type_argc; ++i) {
8841 MonoType *t = dup_type (types [i]);
8843 if (!gclass->inst->is_open)
8844 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8845 if (gclass->inst->is_reference)
8846 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8848 gclass->inst->type_argv [i] = t;
8851 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8853 gclass->container_class = klass;
8855 if (klass->generic_class) {
8856 MonoGenericClass *kgclass = klass->generic_class;
8857 MonoGenericClass *ogclass = gclass;
8859 gclass->context = g_new0 (MonoGenericContext, 1);
8860 gclass->context->container = gclass->container_class->generic_container;
8861 gclass->context->gclass = gclass;
8863 igclass = g_new0 (MonoInflatedGenericClass, 1);
8864 gclass = &igclass->generic_class;
8865 gclass->is_inflated = TRUE;
8867 gclass->inst = g_new0 (MonoGenericInst, 1);
8868 gclass->inst->type_argc = kgclass->inst->type_argc;
8869 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8870 gclass->inst->is_reference = 1;
8872 for (i = 0; i < gclass->inst->type_argc; i++) {
8873 MonoType *t = kgclass->inst->type_argv [i];
8875 t = mono_class_inflate_generic_type (t, ogclass->context);
8877 if (!gclass->inst->is_open)
8878 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8879 if (gclass->inst->is_reference)
8880 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8882 gclass->inst->type_argv [i] = t;
8885 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8887 gclass->container_class = kgclass->container_class;
8890 geninst = g_new0 (MonoType, 1);
8891 geninst->type = MONO_TYPE_GENERICINST;
8893 cached = mono_metadata_lookup_generic_class (gclass);
8896 mono_loader_unlock ();
8897 geninst->data.generic_class = cached;
8901 geninst->data.generic_class = gclass;
8903 gclass->context = g_new0 (MonoGenericContext, 1);
8904 gclass->context->container = gclass->container_class->generic_container;
8905 gclass->context->gclass = gclass;
8907 mono_loader_unlock ();
8912 static inline MonoType*
8913 dup_type (const MonoType *original)
8915 MonoType *r = g_new0 (MonoType, 1);
8917 r->attrs = original->attrs;
8918 r->byref = original->byref;
8919 if (original->type == MONO_TYPE_PTR)
8920 r->data.type = dup_type (original->data.type);
8921 else if (original->type == MONO_TYPE_ARRAY)
8922 r->data.array = mono_dup_array_type (original->data.array);
8923 else if (original->type == MONO_TYPE_FNPTR)
8924 r->data.method = mono_metadata_signature_deep_dup (original->data.method);
8925 mono_stats.generics_metadata_size += sizeof (MonoType);
8929 MonoReflectionMethod*
8930 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8932 MonoMethod *method, *inflated;
8933 MonoReflectionMethodBuilder *mb = NULL;
8934 MonoGenericContainer *container;
8935 MonoGenericMethod *gmethod;
8936 MonoGenericContext *context;
8937 MonoGenericInst *ginst;
8940 MONO_ARCH_SAVE_REGS;
8941 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8942 MonoReflectionTypeBuilder *tb;
8945 mb = (MonoReflectionMethodBuilder *) rmethod;
8946 tb = (MonoReflectionTypeBuilder *) mb->type;
8947 klass = mono_class_from_mono_type (tb->type.type);
8949 method = methodbuilder_to_mono_method (klass, mb);
8951 method = rmethod->method;
8954 method = mono_get_inflated_method (method);
8956 count = mono_method_signature (method)->generic_param_count;
8957 if (count != mono_array_length (types))
8960 container = method->generic_container;
8961 g_assert (container);
8963 if (!container->method_hash)
8964 container->method_hash = g_hash_table_new (
8965 (GHashFunc) mono_metadata_generic_method_hash,
8966 (GCompareFunc) mono_metadata_generic_method_equal);
8968 ginst = g_new0 (MonoGenericInst,1 );
8969 ginst->type_argc = count;
8970 ginst->type_argv = g_new0 (MonoType *, count);
8971 ginst->is_reference = 1;
8972 for (i = 0; i < count; i++) {
8973 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8974 ginst->type_argv [i] = dup_type (garg->type);
8976 if (!ginst->is_open)
8977 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8978 if (ginst->is_reference)
8979 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8981 ginst = mono_metadata_lookup_generic_inst (ginst);
8983 gmethod = g_new0 (MonoGenericMethod, 1);
8984 gmethod->generic_class = method->klass->generic_class;
8985 gmethod->container = container;
8986 gmethod->inst = ginst;
8988 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8992 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8995 gmethod->reflection_info = rmethod;
8997 context = g_new0 (MonoGenericContext, 1);
8998 context->container = container;
8999 context->gclass = method->klass->generic_class;
9000 context->gmethod = gmethod;
9002 if (method->is_inflated)
9003 method = ((MonoMethodInflated *) method)->declaring;
9005 inflated = mono_class_inflate_generic_method (method, context);
9006 g_hash_table_insert (container->method_hash, gmethod, inflated);
9008 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9012 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
9014 MonoGenericMethod *gmethod = NULL;
9015 MonoInflatedGenericClass *gclass;
9016 MonoGenericContext *context;
9020 klass = mono_class_from_mono_type (type->type.type);
9021 gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
9022 n = mono_method_signature (method)->generic_param_count;
9024 context = gclass->generic_class.context;
9025 g_assert (context && context->container);
9027 gmethod = g_new0 (MonoGenericMethod, 1);
9028 gmethod->generic_class = &gclass->generic_class;
9029 gmethod->container = method->generic_container;
9030 gmethod->reflection_info = obj;
9032 gmethod->inst = g_new0 (MonoGenericInst, 1);
9033 gmethod->inst->type_argc = n;
9034 gmethod->inst->type_argv = g_new0 (MonoType *, n);
9036 for (i = 0; i < n; i++) {
9037 MonoGenericParam *gparam = &method->generic_container->type_params [i];
9038 g_assert (gparam->pklass);
9039 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
9042 g_assert (gmethod->container->parent == context->container);
9044 context = g_new0 (MonoGenericContext, 1);
9045 context->container = gmethod->container;
9046 context->gclass = &gclass->generic_class;
9047 context->gmethod = gmethod;
9050 return mono_class_inflate_generic_method (method, context);
9054 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9059 gklass = mono_class_from_mono_type (type->generic_type->type);
9061 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9062 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9063 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9064 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9065 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9066 method = ((MonoReflectionMethod *) obj)->method;
9068 method = NULL; /* prevent compiler warning */
9069 g_assert_not_reached ();
9072 return inflate_mono_method (type, method, obj);
9076 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9077 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9080 MonoGenericClass *gclass;
9081 MonoDynamicGenericClass *dgclass;
9082 MonoClass *klass, *gklass;
9085 MONO_ARCH_SAVE_REGS;
9087 klass = mono_class_from_mono_type (type->type.type);
9088 gclass = type->type.type->data.generic_class;
9090 g_assert (gclass->is_dynamic);
9091 dgclass = (MonoDynamicGenericClass *) gclass;
9093 if (dgclass->initialized)
9096 gklass = gclass->container_class;
9097 mono_class_init (gklass);
9099 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9100 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9101 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9102 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9103 dgclass->count_events = events ? mono_array_length (events) : 0;
9105 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9106 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9107 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9108 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9109 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9111 for (i = 0; i < dgclass->count_methods; i++) {
9112 MonoObject *obj = mono_array_get (methods, gpointer, i);
9114 dgclass->methods [i] = inflate_method (type, obj);
9117 for (i = 0; i < dgclass->count_ctors; i++) {
9118 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9120 dgclass->ctors [i] = inflate_method (type, obj);
9123 for (i = 0; i < dgclass->count_fields; i++) {
9124 MonoObject *obj = mono_array_get (fields, gpointer, i);
9125 MonoClassField *field;
9126 MonoInflatedField *ifield;
9128 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9129 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9130 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9131 field = ((MonoReflectionField *) obj)->field;
9133 field = NULL; /* prevent compiler warning */
9134 g_assert_not_reached ();
9137 ifield = g_new0 (MonoInflatedField, 1);
9138 ifield->generic_type = field->type;
9139 ifield->reflection_info = obj;
9141 dgclass->fields [i] = *field;
9142 dgclass->fields [i].parent = klass;
9143 dgclass->fields [i].generic_info = ifield;
9144 dgclass->fields [i].type = mono_class_inflate_generic_type (
9145 field->type, dgclass->generic_class.generic_class.context);
9148 for (i = 0; i < dgclass->count_properties; i++) {
9149 MonoObject *obj = mono_array_get (properties, gpointer, i);
9150 MonoProperty *property = &dgclass->properties [i];
9152 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9153 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9155 property->parent = klass;
9156 property->attrs = pb->attrs;
9157 property->name = mono_string_to_utf8 (pb->name);
9159 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9161 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9162 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9163 *property = *((MonoReflectionProperty *) obj)->property;
9166 property->get = inflate_mono_method (type, property->get, NULL);
9168 property->set = inflate_mono_method (type, property->set, NULL);
9170 g_assert_not_reached ();
9173 for (i = 0; i < dgclass->count_events; i++) {
9174 MonoObject *obj = mono_array_get (events, gpointer, i);
9175 MonoEvent *event = &dgclass->events [i];
9177 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9178 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9180 event->parent = klass;
9181 event->attrs = eb->attrs;
9182 event->name = mono_string_to_utf8 (eb->name);
9184 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9185 if (eb->remove_method)
9186 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9187 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9188 *event = *((MonoReflectionEvent *) obj)->event;
9191 event->add = inflate_mono_method (type, event->add, NULL);
9193 event->remove = inflate_mono_method (type, event->remove, NULL);
9195 g_assert_not_reached ();
9198 dgclass->initialized = TRUE;
9202 ensure_runtime_vtable (MonoClass *klass)
9204 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9207 if (!tb || klass->wastypebuilder)
9210 ensure_runtime_vtable (klass->parent);
9212 num = tb->ctors? mono_array_length (tb->ctors): 0;
9213 num += tb->num_methods;
9214 klass->method.count = num;
9215 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9216 num = tb->ctors? mono_array_length (tb->ctors): 0;
9217 for (i = 0; i < num; ++i)
9218 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9219 num = tb->num_methods;
9221 for (i = 0; i < num; ++i)
9222 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9224 if (tb->interfaces) {
9225 klass->interface_count = mono_array_length (tb->interfaces);
9226 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9227 for (i = 0; i < klass->interface_count; ++i) {
9228 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9229 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9233 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9234 for (i = 0; i < klass->method.count; ++i)
9235 klass->methods [i]->slot = i;
9237 mono_class_setup_interface_offsets (klass);
9241 * The generic vtable is needed even if image->run is not set since some
9242 * runtime code like ves_icall_Type_GetMethodsByName depends on
9243 * method->slot being defined.
9247 * tb->methods could not be freed since it is used for determining
9248 * overrides during dynamic vtable construction.
9253 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9255 MonoReflectionTypeBuilder *tb;
9261 g_assert (klass->image->dynamic);
9263 if (!klass->reflection_info)
9266 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9268 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9272 for (i = 0; i < tb->num_methods; ++i) {
9273 MonoReflectionMethodBuilder *mb =
9274 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9275 if (mb->override_method)
9281 *overrides = g_new0 (MonoMethod*, onum * 2);
9284 for (i = 0; i < tb->num_methods; ++i) {
9285 MonoReflectionMethodBuilder *mb =
9286 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9287 if (mb->override_method) {
9288 (*overrides) [onum * 2] =
9289 mb->override_method->method;
9290 (*overrides) [onum * 2 + 1] =
9293 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9294 g_assert (mb->override_method->method);
9295 g_assert (mb->mhandle);
9302 *num_overrides = onum;
9306 typebuilder_setup_fields (MonoClass *klass)
9308 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9309 MonoReflectionFieldBuilder *fb;
9310 MonoClassField *field;
9315 klass->field.count = tb->num_fields;
9316 klass->field.first = 0;
9318 if (!klass->field.count)
9321 klass->fields = g_new0 (MonoClassField, klass->field.count);
9323 for (i = 0; i < klass->field.count; ++i) {
9324 fb = mono_array_get (tb->fields, gpointer, i);
9325 field = &klass->fields [i];
9326 field->name = mono_string_to_utf8 (fb->name);
9328 /* FIXME: handle type modifiers */
9329 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9330 field->type->attrs = fb->attrs;
9332 field->type = fb->type->type;
9334 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9335 field->data = mono_array_addr (fb->rva_data, char, 0);
9336 if (fb->offset != -1)
9337 field->offset = fb->offset;
9338 field->parent = klass;
9340 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9342 if (fb->def_value) {
9343 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9344 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9345 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9346 /* Copy the data from the blob since it might get realloc-ed */
9347 p = assembly->blob.data + idx;
9348 len = mono_metadata_decode_blob_size (p, &p2);
9350 field->data = g_malloc (len);
9351 memcpy ((gpointer)field->data, p, len);
9354 mono_class_layout_fields (klass);
9358 typebuilder_setup_properties (MonoClass *klass)
9360 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9361 MonoReflectionPropertyBuilder *pb;
9364 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9365 klass->property.first = 0;
9367 klass->properties = g_new0 (MonoProperty, klass->property.count);
9368 for (i = 0; i < klass->property.count; ++i) {
9369 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9370 klass->properties [i].parent = klass;
9371 klass->properties [i].attrs = pb->attrs;
9372 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9374 klass->properties [i].get = pb->get_method->mhandle;
9376 klass->properties [i].set = pb->set_method->mhandle;
9378 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9382 MonoReflectionEvent *
9383 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9385 MonoEvent *event = g_new0 (MonoEvent, 1);
9389 klass = my_mono_class_from_mono_type (tb->type.type);
9391 event->parent = klass;
9392 event->attrs = eb->attrs;
9393 event->name = mono_string_to_utf8 (eb->name);
9395 event->add = eb->add_method->mhandle;
9396 if (eb->remove_method)
9397 event->remove = eb->remove_method->mhandle;
9398 if (eb->raise_method)
9399 event->raise = eb->raise_method->mhandle;
9401 if (eb->other_methods) {
9402 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9403 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9404 MonoReflectionMethodBuilder *mb =
9405 mono_array_get (eb->other_methods,
9406 MonoReflectionMethodBuilder*, j);
9407 event->other [j] = mb->mhandle;
9411 return mono_event_get_object (mono_object_domain (tb), klass, event);
9415 typebuilder_setup_events (MonoClass *klass)
9417 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9418 MonoReflectionEventBuilder *eb;
9421 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9422 klass->event.first = 0;
9424 klass->events = g_new0 (MonoEvent, klass->event.count);
9425 for (i = 0; i < klass->event.count; ++i) {
9426 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9427 klass->events [i].parent = klass;
9428 klass->events [i].attrs = eb->attrs;
9429 klass->events [i].name = mono_string_to_utf8 (eb->name);
9431 klass->events [i].add = eb->add_method->mhandle;
9432 if (eb->remove_method)
9433 klass->events [i].remove = eb->remove_method->mhandle;
9434 if (eb->raise_method)
9435 klass->events [i].raise = eb->raise_method->mhandle;
9437 if (eb->other_methods) {
9438 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9439 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9440 MonoReflectionMethodBuilder *mb =
9441 mono_array_get (eb->other_methods,
9442 MonoReflectionMethodBuilder*, j);
9443 klass->events [i].other [j] = mb->mhandle;
9450 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9454 MonoReflectionType* res;
9457 MONO_ARCH_SAVE_REGS;
9459 domain = mono_object_domain (tb);
9460 klass = my_mono_class_from_mono_type (tb->type.type);
9462 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9465 * we need to lock the domain because the lock will be taken inside
9466 * So, we need to keep the locking order correct.
9468 mono_domain_lock (domain);
9469 mono_loader_lock ();
9470 if (klass->wastypebuilder) {
9471 mono_loader_unlock ();
9472 mono_domain_unlock (domain);
9473 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9476 * Fields to set in klass:
9477 * the various flags: delegate/unicode/contextbound etc.
9479 klass->flags = tb->attrs;
9480 klass->has_cctor = 1;
9481 klass->has_finalize = 1;
9484 if (!((MonoDynamicImage*)klass->image)->run) {
9485 if (klass->generic_container) {
9486 /* FIXME: The code below can't handle generic classes */
9487 klass->wastypebuilder = TRUE;
9488 mono_loader_unlock ();
9489 mono_domain_unlock (domain);
9490 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9495 /* enums are done right away */
9496 if (!klass->enumtype)
9497 ensure_runtime_vtable (klass);
9500 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9501 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9502 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9506 /* fields and object layout */
9507 if (klass->parent) {
9508 if (!klass->parent->size_inited)
9509 mono_class_init (klass->parent);
9510 klass->instance_size = klass->parent->instance_size;
9511 klass->class_size = 0;
9512 klass->min_align = klass->parent->min_align;
9513 /* if the type has no fields we won't call the field_setup
9514 * routine which sets up klass->has_references.
9516 klass->has_references |= klass->parent->has_references;
9518 klass->instance_size = sizeof (MonoObject);
9519 klass->min_align = 1;
9522 /* FIXME: handle packing_size and instance_size */
9523 typebuilder_setup_fields (klass);
9525 typebuilder_setup_properties (klass);
9527 typebuilder_setup_events (klass);
9529 klass->wastypebuilder = TRUE;
9530 mono_loader_unlock ();
9531 mono_domain_unlock (domain);
9533 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9534 g_assert (res != (MonoReflectionType*)tb);
9540 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9542 MonoGenericParam *param;
9545 MONO_ARCH_SAVE_REGS;
9547 param = g_new0 (MonoGenericParam, 1);
9549 if (gparam->mbuilder) {
9550 if (!gparam->mbuilder->generic_container)
9551 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9552 param->owner = gparam->mbuilder->generic_container;
9553 } else if (gparam->tbuilder) {
9554 g_assert (gparam->tbuilder->generic_container);
9555 param->owner = gparam->tbuilder->generic_container;
9558 param->method = NULL;
9559 param->name = mono_string_to_utf8 (gparam->name);
9560 param->num = gparam->index;
9562 image = &gparam->tbuilder->module->dynamic_image->image;
9563 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9565 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9567 gparam->type.type = g_new0 (MonoType, 1);
9568 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9569 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9570 gparam->type.type->data.generic_param = param;
9574 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9576 MonoDynamicImage *assembly = sig->module->dynamic_image;
9577 guint32 na = mono_array_length (sig->arguments);
9578 guint32 buflen, i, size;
9582 MONO_ARCH_SAVE_REGS;
9584 p = buf = g_malloc (size = 50 + na * 50);
9586 mono_metadata_encode_value (0x07, p, &p);
9587 mono_metadata_encode_value (na, p, &p);
9588 for (i = 0; i < na; ++i) {
9589 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9590 encode_reflection_type (assembly, type, p, &p);
9594 g_assert (buflen < size);
9595 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9596 p = mono_array_addr (result, char, 0);
9597 memcpy (p, buf, buflen);
9604 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9606 MonoDynamicImage *assembly = sig->module->dynamic_image;
9607 guint32 na = mono_array_length (sig->arguments);
9608 guint32 buflen, i, size;
9612 MONO_ARCH_SAVE_REGS;
9614 p = buf = g_malloc (size = 10 + na * 10);
9616 mono_metadata_encode_value (0x06, p, &p);
9617 for (i = 0; i < na; ++i) {
9618 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9619 encode_reflection_type (assembly, type, p, &p);
9623 g_assert (buflen < size);
9624 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9625 p = mono_array_addr (result, char, 0);
9626 memcpy (p, buf, buflen);
9633 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9635 ReflectionMethodBuilder rmb;
9636 MonoMethodSignature *sig;
9639 sig = dynamic_method_to_signature (mb);
9641 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9644 * Resolve references.
9647 * Every second entry in the refs array is reserved for storing handle_class,
9648 * which is needed by the ldtoken implementation in the JIT.
9650 rmb.nrefs = mb->nrefs;
9651 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9652 for (i = 0; i < mb->nrefs; i += 2) {
9653 MonoClass *handle_class;
9654 gpointer ref = resolve_object (mb->module->image,
9655 mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9658 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9661 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9662 rmb.refs [i + 1] = handle_class;
9666 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9670 /* ilgen is no longer needed */
9675 * mono_reflection_lookup_dynamic_token:
9677 * Finish the Builder object pointed to by TOKEN and return the corresponding
9678 * runtime structure. HANDLE_CLASS is set to the class required by
9682 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9684 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9687 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9690 return resolve_object (image, obj, handle_class);
9694 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9696 gpointer result = NULL;
9698 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9699 result = mono_string_intern ((MonoString*)obj);
9700 *handle_class = NULL;
9702 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9703 MonoReflectionType *tb = (MonoReflectionType*)obj;
9704 result = mono_class_from_mono_type (tb->type);
9705 *handle_class = mono_defaults.typehandle_class;
9707 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9708 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9709 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9710 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9711 result = ((MonoReflectionMethod*)obj)->method;
9712 *handle_class = mono_defaults.methodhandle_class;
9714 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9715 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9716 result = mb->mhandle;
9718 /* Type is not yet created */
9719 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9721 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9724 * Hopefully this has been filled in by calling CreateType() on the
9728 * TODO: This won't work if the application finishes another
9729 * TypeBuilder instance instead of this one.
9731 result = mb->mhandle;
9733 *handle_class = mono_defaults.methodhandle_class;
9734 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9735 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9737 result = cb->mhandle;
9739 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9741 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9742 result = cb->mhandle;
9744 *handle_class = mono_defaults.methodhandle_class;
9745 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9746 result = ((MonoReflectionField*)obj)->field;
9747 *handle_class = mono_defaults.fieldhandle_class;
9749 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9750 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9751 result = fb->handle;
9754 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9756 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9757 result = fb->handle;
9759 *handle_class = mono_defaults.fieldhandle_class;
9760 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9761 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9764 klass = tb->type.type->data.klass;
9765 if (klass->wastypebuilder) {
9766 /* Already created */
9770 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9771 result = tb->type.type->data.klass;
9774 *handle_class = mono_defaults.typehandle_class;
9775 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9776 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9777 MonoMethodSignature *sig;
9780 if (helper->arguments)
9781 nargs = mono_array_length (helper->arguments);
9785 sig = mono_metadata_signature_alloc (image, nargs);
9786 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9787 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9789 if (helper->call_conv == 0) /* unmanaged */
9790 sig->call_convention = helper->unmanaged_call_conv - 1;
9792 if (helper->call_conv & 0x02)
9793 sig->call_convention = MONO_CALL_VARARG;
9795 sig->call_convention = MONO_CALL_DEFAULT;
9797 sig->param_count = nargs;
9798 /* TODO: Copy type ? */
9799 sig->ret = helper->return_type->type;
9800 for (i = 0; i < nargs; ++i) {
9801 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9802 sig->params [i] = rt->type;
9806 *handle_class = NULL;
9807 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9808 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9809 /* Already created by the managed code */
9810 g_assert (method->mhandle);
9811 result = method->mhandle;
9812 *handle_class = mono_defaults.methodhandle_class;
9814 g_print (obj->vtable->klass->name);
9815 g_assert_not_reached ();
9821 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9822 const static guint32 declsec_flags_map[] = {
9823 0x00000000, /* empty */
9824 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9825 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9826 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9827 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9828 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9829 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9830 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9831 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9832 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9833 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9834 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9835 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9836 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9837 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9838 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9839 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9840 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9841 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9845 * Returns flags that includes all available security action associated to the handle.
9846 * @token: metadata token (either for a class or a method)
9847 * @image: image where resides the metadata.
9850 mono_declsec_get_flags (MonoImage *image, guint32 token)
9852 guint32 index = mono_metadata_declsec_from_index (image, token);
9853 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9858 for (i = index; i < t->rows; i++) {
9859 guint32 cols [MONO_DECL_SECURITY_SIZE];
9861 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9862 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9865 action = cols [MONO_DECL_SECURITY_ACTION];
9866 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9867 result |= declsec_flags_map [action];
9869 g_assert_not_reached ();
9876 * Get the security actions (in the form of flags) associated with the specified method.
9878 * @method: The method for which we want the declarative security flags.
9879 * Return the declarative security flags for the method (only).
9881 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9882 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9885 mono_declsec_flags_from_method (MonoMethod *method)
9887 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9888 /* FIXME: No cache (for the moment) */
9889 guint32 idx = mono_method_get_index (method);
9890 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9891 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9892 return mono_declsec_get_flags (method->klass->image, idx);
9898 * Get the security actions (in the form of flags) associated with the specified class.
9900 * @klass: The class for which we want the declarative security flags.
9901 * Return the declarative security flags for the class.
9903 * Note: We cache the flags inside the MonoClass structure as this will get
9904 * called very often (at least for each method).
9907 mono_declsec_flags_from_class (MonoClass *klass)
9909 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9910 if (!klass->declsec_flags) {
9911 guint32 idx = mono_metadata_token_index (klass->type_token);
9912 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9913 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9914 /* we cache the flags on classes */
9915 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9917 return klass->declsec_flags;
9923 * Get the security actions (in the form of flags) associated with the specified assembly.
9925 * @assembly: The assembly for which we want the declarative security flags.
9926 * Return the declarative security flags for the assembly.
9929 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9931 guint32 idx = 1; /* there is only one assembly */
9932 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9933 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9934 return mono_declsec_get_flags (assembly->image, idx);
9939 * Fill actions for the specific index (which may either be an encoded class token or
9940 * an encoded method token) from the metadata image.
9941 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9944 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9945 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9947 MonoBoolean result = FALSE;
9949 guint32 cols [MONO_DECL_SECURITY_SIZE];
9950 int index = mono_metadata_declsec_from_index (image, token);
9953 t = &image->tables [MONO_TABLE_DECLSECURITY];
9954 for (i = index; i < t->rows; i++) {
9955 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9957 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9960 /* if present only replace (class) permissions with method permissions */
9961 /* if empty accept either class or method permissions */
9962 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9963 if (!actions->demand.blob) {
9964 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9965 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9966 actions->demand.blob = (char*) (blob + 2);
9967 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9970 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9971 if (!actions->noncasdemand.blob) {
9972 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9973 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9974 actions->noncasdemand.blob = (char*) (blob + 2);
9975 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9978 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9979 if (!actions->demandchoice.blob) {
9980 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9981 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9982 actions->demandchoice.blob = (char*) (blob + 2);
9983 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9993 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9994 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9996 guint32 idx = mono_metadata_token_index (klass->type_token);
9997 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9998 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9999 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
10003 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
10004 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10006 guint32 idx = mono_method_get_index (method);
10007 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10008 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10009 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10013 * Collect all actions (that requires to generate code in mini) assigned for
10014 * the specified method.
10015 * Note: Don't use the content of actions if the function return FALSE.
10018 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10020 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
10021 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10022 MonoBoolean result = FALSE;
10025 /* quick exit if no declarative security is present in the metadata */
10026 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10029 /* we want the original as the wrapper is "free" of the security informations */
10030 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10031 method = mono_marshal_method_from_wrapper (method);
10036 /* First we look for method-level attributes */
10037 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10038 mono_class_init (method->klass);
10039 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10041 result = mono_declsec_get_method_demands_params (method, demands,
10042 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10045 /* Here we use (or create) the class declarative cache to look for demands */
10046 flags = mono_declsec_flags_from_class (method->klass);
10047 if (flags & mask) {
10049 mono_class_init (method->klass);
10050 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10052 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10053 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10056 /* The boolean return value is used as a shortcut in case nothing needs to
10057 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10063 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10065 * Note: Don't use the content of actions if the function return FALSE.
10068 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10070 MonoBoolean result = FALSE;
10073 /* quick exit if no declarative security is present in the metadata */
10074 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10077 /* we want the original as the wrapper is "free" of the security informations */
10078 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10079 method = mono_marshal_method_from_wrapper (method);
10084 /* results are independant - zeroize both */
10085 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10086 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10088 /* First we look for method-level attributes */
10089 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10090 mono_class_init (method->klass);
10092 result = mono_declsec_get_method_demands_params (method, cmethod,
10093 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10096 /* Here we use (or create) the class declarative cache to look for demands */
10097 flags = mono_declsec_flags_from_class (method->klass);
10098 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10099 mono_class_init (method->klass);
10101 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10102 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10109 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10111 * @klass The inherited class - this is the class that provides the security check (attributes)
10113 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10115 * Note: Don't use the content of actions if the function return FALSE.
10118 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10120 MonoBoolean result = FALSE;
10123 /* quick exit if no declarative security is present in the metadata */
10124 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10127 /* Here we use (or create) the class declarative cache to look for demands */
10128 flags = mono_declsec_flags_from_class (klass);
10129 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10130 mono_class_init (klass);
10131 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10133 result |= mono_declsec_get_class_demands_params (klass, demands,
10134 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10141 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10143 * Note: Don't use the content of actions if the function return FALSE.
10146 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10148 /* quick exit if no declarative security is present in the metadata */
10149 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10152 /* we want the original as the wrapper is "free" of the security informations */
10153 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10154 method = mono_marshal_method_from_wrapper (method);
10159 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10160 mono_class_init (method->klass);
10161 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10163 return mono_declsec_get_method_demands_params (method, demands,
10164 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10171 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10173 guint32 cols [MONO_DECL_SECURITY_SIZE];
10177 int index = mono_metadata_declsec_from_index (image, token);
10181 t = &image->tables [MONO_TABLE_DECLSECURITY];
10182 for (i = index; i < t->rows; i++) {
10183 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10185 /* shortcut - index are ordered */
10186 if (token != cols [MONO_DECL_SECURITY_PARENT])
10189 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10190 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10191 entry->blob = (char*) (metadata + 2);
10192 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10201 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10203 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10204 guint32 idx = mono_method_get_index (method);
10205 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10206 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10207 return get_declsec_action (method->klass->image, idx, action, entry);
10213 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10216 guint32 flags = mono_declsec_flags_from_class (klass);
10217 if (declsec_flags_map [action] & flags) {
10218 guint32 idx = mono_metadata_token_index (klass->type_token);
10219 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10220 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10221 return get_declsec_action (klass->image, idx, action, entry);
10227 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10229 guint32 idx = 1; /* there is only one assembly */
10230 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10231 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10233 return get_declsec_action (assembly->image, idx, action, entry);
10237 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10239 MonoObject *res, *exc;
10241 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10242 static MonoMethod *method = NULL;
10244 if (!System_Reflection_Emit_TypeBuilder) {
10245 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10246 g_assert (System_Reflection_Emit_TypeBuilder);
10248 if (method == NULL) {
10249 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10254 * The result of mono_type_get_object () might be a System.MonoType but we
10255 * need a TypeBuilder so use klass->reflection_info.
10257 g_assert (klass->reflection_info);
10258 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10260 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10262 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10266 return *(MonoBoolean*)mono_object_unbox (res);