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 MonoArray *return_modreq;
60 MonoArray *return_modopt;
61 MonoArray *param_modreq;
62 MonoArray *param_modopt;
63 MonoArray *permissions;
68 int charset, extra_flags, native_cc;
69 MonoString *dll, *dllentry;
70 } ReflectionMethodBuilder;
74 MonoReflectionGenericParam *gparam;
75 } GenericParamTableEntry;
77 const unsigned char table_sizes [MONO_TABLE_NUM] = {
87 MONO_INTERFACEIMPL_SIZE,
88 MONO_MEMBERREF_SIZE, /* 0x0A */
90 MONO_CUSTOM_ATTR_SIZE,
91 MONO_FIELD_MARSHAL_SIZE,
92 MONO_DECL_SECURITY_SIZE,
93 MONO_CLASS_LAYOUT_SIZE,
94 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
95 MONO_STAND_ALONE_SIGNATURE_SIZE,
99 MONO_PROPERTY_MAP_SIZE,
102 MONO_METHOD_SEMA_SIZE,
103 MONO_METHODIMPL_SIZE,
104 MONO_MODULEREF_SIZE, /* 0x1A */
110 MONO_ASSEMBLY_SIZE, /* 0x20 */
111 MONO_ASSEMBLY_PROCESSOR_SIZE,
112 MONO_ASSEMBLYOS_SIZE,
113 MONO_ASSEMBLYREF_SIZE,
114 MONO_ASSEMBLYREFPROC_SIZE,
115 MONO_ASSEMBLYREFOS_SIZE,
119 MONO_NESTED_CLASS_SIZE,
121 MONO_GENERICPARAM_SIZE, /* 0x2A */
122 MONO_METHODSPEC_SIZE,
123 MONO_GENPARCONSTRAINT_SIZE
127 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
128 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
129 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
130 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
131 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
132 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
133 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
134 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
135 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
136 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
137 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
138 static void ensure_runtime_vtable (MonoClass *klass);
139 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class);
140 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
141 static guint32 type_get_signature_size (MonoType *type);
142 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
143 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
144 static inline MonoType *dup_type (const MonoType *original);
149 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
153 mp_g_malloc (MonoMemPool *mp, guint size)
156 return mono_mempool_alloc (mp, size);
158 return g_malloc (size);
164 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
168 mp_g_malloc0 (MonoMemPool *mp, guint size)
171 return mono_mempool_alloc0 (mp, size);
173 return g_malloc0 (size);
176 #define mp_g_new(mp,struct_type, n_structs) \
177 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
179 #define mp_g_new0(mp,struct_type, n_structs) \
180 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
183 alloc_table (MonoDynamicTable *table, guint nrows)
186 g_assert (table->columns);
187 if (nrows + 1 >= table->alloc_rows) {
188 while (nrows + 1 >= table->alloc_rows) {
189 if (table->alloc_rows == 0)
190 table->alloc_rows = 16;
192 table->alloc_rows *= 2;
195 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
200 make_room_in_stream (MonoDynamicStream *stream, int size)
202 if (size <= stream->alloc_size)
205 while (stream->alloc_size <= size) {
206 if (stream->alloc_size < 4096)
207 stream->alloc_size = 4096;
209 stream->alloc_size *= 2;
212 stream->data = g_realloc (stream->data, stream->alloc_size);
216 string_heap_insert (MonoDynamicStream *sh, const char *str)
220 gpointer oldkey, oldval;
222 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
223 return GPOINTER_TO_UINT (oldval);
225 len = strlen (str) + 1;
228 make_room_in_stream (sh, idx + len);
231 * We strdup the string even if we already copy them in sh->data
232 * so that the string pointers in the hash remain valid even if
233 * we need to realloc sh->data. We may want to avoid that later.
235 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
236 memcpy (sh->data + idx, str, len);
242 string_heap_init (MonoDynamicStream *sh)
245 sh->alloc_size = 4096;
246 sh->data = g_malloc (4096);
247 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
248 string_heap_insert (sh, "");
252 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
256 make_room_in_stream (stream, stream->index + len);
257 memcpy (stream->data + stream->index, data, len);
259 stream->index += len;
261 * align index? Not without adding an additional param that controls it since
262 * we may store a blob value in pieces.
268 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
272 make_room_in_stream (stream, stream->index + len);
273 memset (stream->data + stream->index, 0, len);
275 stream->index += len;
280 stream_data_align (MonoDynamicStream *stream)
283 guint32 count = stream->index % 4;
285 /* we assume the stream data will be aligned */
287 mono_image_add_stream_data (stream, buf, 4 - count);
291 mono_blob_entry_hash (const char* str)
295 len = mono_metadata_decode_blob_size (str, &str);
299 for (str += 1; str < end; str++)
300 h = (h << 5) - h + *str;
308 mono_blob_entry_equal (const char *str1, const char *str2) {
312 len = mono_metadata_decode_blob_size (str1, &end1);
313 len2 = mono_metadata_decode_blob_size (str2, &end2);
316 return memcmp (end1, end2, len) == 0;
320 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
324 gpointer oldkey, oldval;
326 copy = g_malloc (s1+s2);
327 memcpy (copy, b1, s1);
328 memcpy (copy + s1, b2, s2);
329 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
331 idx = GPOINTER_TO_UINT (oldval);
333 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
334 mono_image_add_stream_data (&assembly->blob, b2, s2);
335 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
341 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
342 * dest may be misaligned.
345 swap_with_size (char *dest, const char* val, int len, int nelem) {
346 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
349 for (elem = 0; elem < nelem; ++elem) {
375 g_assert_not_reached ();
381 memcpy (dest, val, len * nelem);
386 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
390 guint32 idx = 0, len;
392 len = str->length * 2;
393 mono_metadata_encode_value (len, b, &b);
394 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
396 char *swapped = g_malloc (2 * mono_string_length (str));
397 const char *p = (const char*)mono_string_chars (str);
399 swap_with_size (swapped, p, 2, mono_string_length (str));
400 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
404 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
409 /* modified version needed to handle building corlib */
411 my_mono_class_from_mono_type (MonoType *type) {
412 switch (type->type) {
413 case MONO_TYPE_ARRAY:
415 case MONO_TYPE_SZARRAY:
416 case MONO_TYPE_GENERICINST:
417 return mono_class_from_mono_type (type);
420 g_assert (type->data.generic_param->pklass);
421 return type->data.generic_param->pklass;
423 /* should be always valid when we reach this case... */
424 return type->data.klass;
429 default_class_from_mono_type (MonoType *type)
431 switch (type->type) {
432 case MONO_TYPE_OBJECT:
433 return mono_defaults.object_class;
435 return mono_defaults.void_class;
436 case MONO_TYPE_BOOLEAN:
437 return mono_defaults.boolean_class;
439 return mono_defaults.char_class;
441 return mono_defaults.sbyte_class;
443 return mono_defaults.byte_class;
445 return mono_defaults.int16_class;
447 return mono_defaults.uint16_class;
449 return mono_defaults.int32_class;
451 return mono_defaults.uint32_class;
453 return mono_defaults.int_class;
455 return mono_defaults.uint_class;
457 return mono_defaults.int64_class;
459 return mono_defaults.uint64_class;
461 return mono_defaults.single_class;
463 return mono_defaults.double_class;
464 case MONO_TYPE_STRING:
465 return mono_defaults.string_class;
467 g_warning ("implement me 0x%02x\n", type->type);
468 g_assert_not_reached ();
475 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char *p, char **endbuf)
480 g_assert_not_reached ();
484 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
485 encode_type (assembly, &gclass->container_class->byval_arg, p, &p);
486 mono_metadata_encode_value (gclass->inst->type_argc, p, &p);
487 for (i = 0; i < gclass->inst->type_argc; ++i)
488 encode_type (assembly, gclass->inst->type_argv [i], p, &p);
494 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
497 g_assert_not_reached ();
502 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
506 case MONO_TYPE_BOOLEAN:
520 case MONO_TYPE_STRING:
521 case MONO_TYPE_OBJECT:
522 case MONO_TYPE_TYPEDBYREF:
523 mono_metadata_encode_value (type->type, p, &p);
526 mono_metadata_encode_value (type->type, p, &p);
527 encode_type (assembly, type->data.type, p, &p);
529 case MONO_TYPE_SZARRAY:
530 mono_metadata_encode_value (type->type, p, &p);
531 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
533 case MONO_TYPE_VALUETYPE:
534 case MONO_TYPE_CLASS: {
535 MonoClass *k = mono_class_from_mono_type (type);
537 * Make sure we use the correct type.
539 mono_metadata_encode_value (k->byval_arg.type, p, &p);
541 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
542 * otherwise two typerefs could point to the same type, leading to
543 * verification errors.
545 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
548 case MONO_TYPE_ARRAY:
549 mono_metadata_encode_value (type->type, p, &p);
550 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
551 mono_metadata_encode_value (type->data.array->rank, p, &p);
552 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
553 mono_metadata_encode_value (0, p, &p);
555 case MONO_TYPE_GENERICINST:
556 encode_generic_class (assembly, type->data.generic_class, p, &p);
560 mono_metadata_encode_value (type->type, p, &p);
561 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
564 g_error ("need to encode type %x", type->type);
570 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
573 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
577 encode_type (assembly, type->type, p, endbuf);
581 g_assert_not_reached ();
586 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
591 for (i = 0; i < mono_array_length (modreq); ++i) {
592 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
593 *p = MONO_TYPE_CMOD_REQD;
595 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
599 for (i = 0; i < mono_array_length (modopt); ++i) {
600 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
601 *p = MONO_TYPE_CMOD_OPT;
603 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
610 generic_class_get_signature_size (MonoGenericClass *gclass)
616 g_assert_not_reached ();
619 size += 1 + type_get_signature_size (&gclass->container_class->byval_arg);
621 for (i = 0; i < gclass->inst->type_argc; ++i)
622 size += type_get_signature_size (gclass->inst->type_argv [i]);
628 type_get_signature_size (MonoType *type)
633 g_assert_not_reached ();
641 case MONO_TYPE_BOOLEAN:
655 case MONO_TYPE_STRING:
656 case MONO_TYPE_OBJECT:
657 case MONO_TYPE_TYPEDBYREF:
660 return size + 1 + type_get_signature_size (type->data.type);
661 case MONO_TYPE_SZARRAY:
662 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
663 case MONO_TYPE_VALUETYPE:
664 case MONO_TYPE_CLASS:
666 case MONO_TYPE_ARRAY:
667 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
668 case MONO_TYPE_GENERICINST:
669 return size + generic_class_get_signature_size (type->data.generic_class);
674 g_error ("need to encode type %x", type->type);
680 method_get_signature_size (MonoMethodSignature *sig)
685 size = type_get_signature_size (sig->ret);
686 for (i = 0; i < sig->param_count; i++)
687 size += type_get_signature_size (sig->params [i]);
689 if (sig->generic_param_count)
691 if (sig->sentinelpos >= 0)
698 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
703 guint32 nparams = sig->param_count;
704 guint32 size = 11 + method_get_signature_size (sig);
712 p = buf = g_malloc (size);
714 * FIXME: vararg, explicit_this, differenc call_conv values...
716 *p = sig->call_convention;
718 *p |= 0x20; /* hasthis */
719 if (sig->generic_param_count)
720 *p |= 0x10; /* generic */
722 if (sig->generic_param_count)
723 mono_metadata_encode_value (sig->generic_param_count, p, &p);
724 mono_metadata_encode_value (nparams, p, &p);
725 encode_type (assembly, sig->ret, p, &p);
726 for (i = 0; i < nparams; ++i) {
727 if (i == sig->sentinelpos)
728 *p++ = MONO_TYPE_SENTINEL;
729 encode_type (assembly, sig->params [i], p, &p);
732 g_assert (p - buf < size);
733 mono_metadata_encode_value (p-buf, b, &b);
734 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
740 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
743 * FIXME: reuse code from method_encode_signature().
748 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
749 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
750 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
751 guint32 size = 41 + nparams * 40 + notypes * 40;
756 p = buf = g_malloc (size);
757 /* LAMESPEC: all the call conv spec is foobared */
758 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
759 if (mb->call_conv & 2)
760 *p |= 0x5; /* vararg */
761 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
762 *p |= 0x20; /* hasthis */
764 *p |= 0x10; /* generic */
767 mono_metadata_encode_value (ngparams, p, &p);
768 mono_metadata_encode_value (nparams + notypes, p, &p);
769 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
770 encode_reflection_type (assembly, mb->rtype, p, &p);
771 for (i = 0; i < nparams; ++i) {
772 MonoArray *modreq = NULL;
773 MonoArray *modopt = NULL;
774 MonoReflectionType *pt;
776 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
777 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
778 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
779 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
780 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
781 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
782 encode_reflection_type (assembly, pt, p, &p);
785 *p++ = MONO_TYPE_SENTINEL;
786 for (i = 0; i < notypes; ++i) {
787 MonoReflectionType *pt;
789 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
790 encode_reflection_type (assembly, pt, p, &p);
794 g_assert (p - buf < size);
795 mono_metadata_encode_value (p-buf, b, &b);
796 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
802 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
804 MonoDynamicTable *table;
807 guint32 idx, sig_idx, size;
808 guint nl = mono_array_length (ilgen->locals);
815 p = buf = g_malloc (size);
816 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
817 idx = table->next_idx ++;
819 alloc_table (table, table->rows);
820 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
822 mono_metadata_encode_value (0x07, p, &p);
823 mono_metadata_encode_value (nl, p, &p);
824 for (i = 0; i < nl; ++i) {
825 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
828 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
830 encode_reflection_type (assembly, lb->type, p, &p);
832 g_assert (p - buf < size);
833 mono_metadata_encode_value (p-buf, b, &b);
834 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
837 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
843 method_count_clauses (MonoReflectionILGen *ilgen)
845 guint32 num_clauses = 0;
848 MonoILExceptionInfo *ex_info;
849 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
850 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
851 if (ex_info->handlers)
852 num_clauses += mono_array_length (ex_info->handlers);
860 static MonoExceptionClause*
861 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
863 MonoExceptionClause *clauses;
864 MonoExceptionClause *clause;
865 MonoILExceptionInfo *ex_info;
866 MonoILExceptionBlock *ex_block;
867 guint32 finally_start;
868 int i, j, clause_index;;
870 clauses = g_new0 (MonoExceptionClause, num_clauses);
873 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
874 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
875 finally_start = ex_info->start + ex_info->len;
876 if (!ex_info->handlers)
878 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
879 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
880 clause = &(clauses [clause_index]);
882 clause->flags = ex_block->type;
883 clause->try_offset = ex_info->start;
885 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
886 clause->try_len = finally_start - ex_info->start;
888 clause->try_len = ex_info->len;
889 clause->handler_offset = ex_block->start;
890 clause->handler_len = ex_block->len;
891 if (ex_block->extype) {
892 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
894 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
895 clause->data.filter_offset = ex_block->filter_offset;
897 clause->data.filter_offset = 0;
899 finally_start = ex_block->start + ex_block->len;
909 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
915 gint32 num_locals = 0;
916 gint32 num_exception = 0;
919 char fat_header [12];
922 guint32 local_sig = 0;
923 guint32 header_size = 12;
926 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
927 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
931 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
933 code = mb->ilgen->code;
934 code_size = mb->ilgen->code_len;
935 max_stack = mb->ilgen->max_stack;
936 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
937 if (mb->ilgen->ex_handlers)
938 num_exception = method_count_clauses (mb->ilgen);
942 char *name = mono_string_to_utf8 (mb->name);
943 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
944 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
947 mono_raise_exception (exception);
950 code_size = mono_array_length (code);
951 max_stack = 8; /* we probably need to run a verifier on the code... */
954 stream_data_align (&assembly->code);
956 /* check for exceptions, maxstack, locals */
957 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
959 if (code_size < 64 && !(code_size & 1)) {
960 flags = (code_size << 2) | 0x2;
961 } else if (code_size < 32 && (code_size & 1)) {
962 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
966 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
967 /* add to the fixup todo list */
968 if (mb->ilgen && mb->ilgen->num_token_fixups)
969 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
970 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
971 return assembly->text_rva + idx;
975 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
977 * FIXME: need to set also the header size in fat_flags.
978 * (and more sects and init locals flags)
982 fat_flags |= METHOD_HEADER_MORE_SECTS;
984 fat_flags |= METHOD_HEADER_INIT_LOCALS;
985 fat_header [0] = fat_flags;
986 fat_header [1] = (header_size / 4 ) << 4;
987 short_value = GUINT16_TO_LE (max_stack);
988 memcpy (fat_header + 2, &short_value, 2);
989 int_value = GUINT32_TO_LE (code_size);
990 memcpy (fat_header + 4, &int_value, 4);
991 int_value = GUINT32_TO_LE (local_sig);
992 memcpy (fat_header + 8, &int_value, 4);
993 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
994 /* add to the fixup todo list */
995 if (mb->ilgen && mb->ilgen->num_token_fixups)
996 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
998 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1000 unsigned char sheader [4];
1001 MonoILExceptionInfo * ex_info;
1002 MonoILExceptionBlock * ex_block;
1005 stream_data_align (&assembly->code);
1006 /* always use fat format for now */
1007 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1008 num_exception *= 6 * sizeof (guint32);
1009 num_exception += 4; /* include the size of the header */
1010 sheader [1] = num_exception & 0xff;
1011 sheader [2] = (num_exception >> 8) & 0xff;
1012 sheader [3] = (num_exception >> 16) & 0xff;
1013 mono_image_add_stream_data (&assembly->code, sheader, 4);
1014 /* fat header, so we are already aligned */
1016 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1017 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1018 if (ex_info->handlers) {
1019 int finally_start = ex_info->start + ex_info->len;
1020 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1022 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1024 val = GUINT32_TO_LE (ex_block->type);
1025 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1027 val = GUINT32_TO_LE (ex_info->start);
1028 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1029 /* need fault, too, probably */
1030 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1031 val = GUINT32_TO_LE (finally_start - ex_info->start);
1033 val = GUINT32_TO_LE (ex_info->len);
1034 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1035 /* handler offset */
1036 val = GUINT32_TO_LE (ex_block->start);
1037 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1039 val = GUINT32_TO_LE (ex_block->len);
1040 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1041 finally_start = ex_block->start + ex_block->len;
1042 if (ex_block->extype) {
1043 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1045 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1046 val = ex_block->filter_offset;
1050 val = GUINT32_TO_LE (val);
1051 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1052 /*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",
1053 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);*/
1056 g_error ("No clauses for ex info block %d", i);
1060 return assembly->text_rva + idx;
1064 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1067 MonoDynamicTable *table;
1070 table = &assembly->tables [table_idx];
1072 g_assert (col < table->columns);
1074 values = table->values + table->columns;
1075 for (i = 1; i <= table->rows; ++i) {
1076 if (values [col] == token)
1078 values += table->columns;
1083 static GHashTable *dynamic_custom_attrs = NULL;
1086 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1088 /* FIXME: Need to do more checks */
1089 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1090 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1092 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1099 static MonoCustomAttrInfo*
1100 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1102 int i, index, count, not_visible;
1103 MonoCustomAttrInfo *ainfo;
1104 MonoReflectionCustomAttr *cattr;
1108 /* FIXME: check in assembly the Run flag is set */
1110 count = mono_array_length (cattrs);
1112 /* Skip nonpublic attributes since MS.NET seems to do the same */
1113 /* FIXME: This needs to be done more globally */
1115 for (i = 0; i < count; ++i) {
1116 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1117 if (!custom_attr_visible (image, cattr))
1120 count -= not_visible;
1122 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1124 ainfo->image = image;
1125 ainfo->num_attrs = count;
1127 for (i = 0; i < count; ++i) {
1128 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1129 if (custom_attr_visible (image, cattr)) {
1130 ainfo->attrs [index].ctor = cattr->ctor->method;
1131 /* FIXME: might want to memdup the data here */
1132 ainfo->attrs [index].data = mono_array_addr (cattr->data, char, 0);
1133 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1142 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1144 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1149 if (!dynamic_custom_attrs)
1150 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1152 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1153 ainfo->cached = TRUE;
1157 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1164 * idx is the table index of the object
1165 * type is one of MONO_CUSTOM_ATTR_*
1168 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1170 MonoDynamicTable *table;
1171 MonoReflectionCustomAttr *cattr;
1173 guint32 count, i, token;
1175 char *p = blob_size;
1177 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1180 count = mono_array_length (cattrs);
1181 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1182 table->rows += count;
1183 alloc_table (table, table->rows);
1184 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1185 idx <<= MONO_CUSTOM_ATTR_BITS;
1187 for (i = 0; i < count; ++i) {
1188 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1189 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1190 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1191 type = mono_metadata_token_index (token);
1192 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1193 switch (mono_metadata_token_table (token)) {
1194 case MONO_TABLE_METHOD:
1195 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1197 case MONO_TABLE_MEMBERREF:
1198 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1201 g_warning ("got wrong token in custom attr");
1204 values [MONO_CUSTOM_ATTR_TYPE] = type;
1206 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1207 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1208 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1209 values += MONO_CUSTOM_ATTR_SIZE;
1215 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1217 MonoDynamicTable *table;
1219 guint32 count, i, idx;
1220 MonoReflectionPermissionSet *perm;
1225 count = mono_array_length (permissions);
1226 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1227 table->rows += count;
1228 alloc_table (table, table->rows);
1230 for (i = 0; i < mono_array_length (permissions); ++i) {
1231 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1233 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1235 idx = mono_metadata_token_index (parent_token);
1236 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1237 switch (mono_metadata_token_table (parent_token)) {
1238 case MONO_TABLE_TYPEDEF:
1239 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1241 case MONO_TABLE_METHOD:
1242 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1244 case MONO_TABLE_ASSEMBLY:
1245 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1248 g_assert_not_reached ();
1251 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1252 values [MONO_DECL_SECURITY_PARENT] = idx;
1253 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1260 * Fill in the MethodDef and ParamDef tables for a method.
1261 * This is used for both normal methods and constructors.
1264 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1266 MonoDynamicTable *table;
1271 /* room in this table is already allocated */
1272 table = &assembly->tables [MONO_TABLE_METHOD];
1273 *mb->table_idx = table->next_idx ++;
1274 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1275 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1276 name = mono_string_to_utf8 (mb->name);
1277 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1279 values [MONO_METHOD_FLAGS] = mb->attrs;
1280 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1281 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1282 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1284 table = &assembly->tables [MONO_TABLE_PARAM];
1285 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1287 mono_image_add_decl_security (assembly,
1288 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1291 MonoDynamicTable *mtable;
1294 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1295 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1298 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1299 if (mono_array_get (mb->pinfo, gpointer, i))
1302 table->rows += count;
1303 alloc_table (table, table->rows);
1304 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1305 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1306 MonoReflectionParamBuilder *pb;
1307 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1308 values [MONO_PARAM_FLAGS] = pb->attrs;
1309 values [MONO_PARAM_SEQUENCE] = i;
1310 if (pb->name != NULL) {
1311 name = mono_string_to_utf8 (pb->name);
1312 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1315 values [MONO_PARAM_NAME] = 0;
1317 values += MONO_PARAM_SIZE;
1318 if (pb->marshal_info) {
1320 alloc_table (mtable, mtable->rows);
1321 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1322 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1323 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1325 pb->table_idx = table->next_idx++;
1326 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1327 guint32 field_type = 0;
1328 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1330 alloc_table (mtable, mtable->rows);
1331 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1332 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1333 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1334 mvalues [MONO_CONSTANT_TYPE] = field_type;
1335 mvalues [MONO_CONSTANT_PADDING] = 0;
1343 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1345 rmb->ilgen = mb->ilgen;
1346 rmb->rtype = mb->rtype;
1347 rmb->parameters = mb->parameters;
1348 rmb->generic_params = mb->generic_params;
1349 rmb->generic_container = mb->generic_container;
1350 rmb->opt_types = NULL;
1351 rmb->pinfo = mb->pinfo;
1352 rmb->attrs = mb->attrs;
1353 rmb->iattrs = mb->iattrs;
1354 rmb->call_conv = mb->call_conv;
1355 rmb->code = mb->code;
1356 rmb->type = mb->type;
1357 rmb->name = mb->name;
1358 rmb->table_idx = &mb->table_idx;
1359 rmb->init_locals = mb->init_locals;
1360 rmb->return_modreq = mb->return_modreq;
1361 rmb->return_modopt = mb->return_modopt;
1362 rmb->param_modreq = mb->param_modreq;
1363 rmb->param_modopt = mb->param_modopt;
1364 rmb->permissions = mb->permissions;
1365 rmb->mhandle = mb->mhandle;
1370 rmb->charset = mb->charset;
1371 rmb->extra_flags = mb->extra_flags;
1372 rmb->native_cc = mb->native_cc;
1373 rmb->dllentry = mb->dllentry;
1379 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1381 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1383 rmb->ilgen = mb->ilgen;
1384 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1385 rmb->parameters = mb->parameters;
1386 rmb->generic_params = NULL;
1387 rmb->generic_container = NULL;
1388 rmb->opt_types = NULL;
1389 rmb->pinfo = mb->pinfo;
1390 rmb->attrs = mb->attrs;
1391 rmb->iattrs = mb->iattrs;
1392 rmb->call_conv = mb->call_conv;
1394 rmb->type = mb->type;
1395 rmb->name = mono_string_new (mono_domain_get (), name);
1396 rmb->table_idx = &mb->table_idx;
1397 rmb->init_locals = mb->init_locals;
1398 rmb->return_modreq = NULL;
1399 rmb->return_modopt = NULL;
1400 rmb->param_modreq = mb->param_modreq;
1401 rmb->param_modopt = mb->param_modopt;
1402 rmb->permissions = mb->permissions;
1403 rmb->mhandle = mb->mhandle;
1409 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1411 rmb->ilgen = mb->ilgen;
1412 rmb->rtype = mb->rtype;
1413 rmb->parameters = mb->parameters;
1414 rmb->generic_params = NULL;
1415 rmb->generic_container = NULL;
1416 rmb->opt_types = NULL;
1418 rmb->attrs = mb->attrs;
1420 rmb->call_conv = mb->call_conv;
1423 rmb->name = mb->name;
1424 rmb->table_idx = NULL;
1425 rmb->init_locals = mb->init_locals;
1426 rmb->return_modreq = NULL;
1427 rmb->return_modopt = NULL;
1428 rmb->param_modreq = NULL;
1429 rmb->param_modopt = NULL;
1430 rmb->permissions = NULL;
1431 rmb->mhandle = mb->mhandle;
1437 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1439 MonoDynamicTable *table;
1442 ReflectionMethodBuilder rmb;
1445 reflection_methodbuilder_from_method_builder (&rmb, mb);
1447 mono_image_basic_method (&rmb, assembly);
1448 mb->table_idx = *rmb.table_idx;
1450 if (mb->dll) { /* It's a P/Invoke method */
1452 /* map CharSet values to on-disk values */
1453 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1454 int extra_flags = mb->extra_flags;
1455 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1457 alloc_table (table, table->rows);
1458 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1460 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1461 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1463 name = mono_string_to_utf8 (mb->dllentry);
1465 name = mono_string_to_utf8 (mb->name);
1466 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1468 name = mono_string_to_utf8 (mb->dll);
1469 moduleref = string_heap_insert (&assembly->sheap, name);
1471 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1472 table = &assembly->tables [MONO_TABLE_MODULEREF];
1474 alloc_table (table, table->rows);
1475 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1476 values [MONO_IMPLMAP_SCOPE] = table->rows;
1480 if (mb->override_method) {
1481 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1483 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1485 alloc_table (table, table->rows);
1486 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1487 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1488 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1490 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1491 switch (mono_metadata_token_table (tok)) {
1492 case MONO_TABLE_MEMBERREF:
1493 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1495 case MONO_TABLE_METHOD:
1496 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1499 g_assert_not_reached ();
1501 values [MONO_METHODIMPL_DECLARATION] = tok;
1504 if (mb->generic_params) {
1505 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1506 table->rows += mono_array_length (mb->generic_params);
1507 alloc_table (table, table->rows);
1508 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1509 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1511 mono_image_get_generic_param_info (
1512 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1519 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1521 ReflectionMethodBuilder rmb;
1523 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1525 mono_image_basic_method (&rmb, assembly);
1526 mb->table_idx = *rmb.table_idx;
1530 type_get_fully_qualified_name (MonoType *type)
1532 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1536 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1540 klass = my_mono_class_from_mono_type (type);
1542 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1543 ta = klass->image->assembly;
1544 if (ta->dynamic || (ta == ass))
1545 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1547 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1551 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1553 char blob_size [64];
1554 char *b = blob_size;
1559 if (!assembly->save)
1562 p = buf = g_malloc (256);
1564 mono_metadata_encode_value (0x06, p, &p);
1565 /* encode custom attributes before the type */
1566 encode_type (assembly, type, p, &p);
1567 g_assert (p-buf < 256);
1568 mono_metadata_encode_value (p-buf, b, &b);
1569 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1575 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1577 char blob_size [64];
1578 char *b = blob_size;
1583 p = buf = g_malloc (256);
1585 mono_metadata_encode_value (0x06, p, &p);
1586 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1587 /* encode custom attributes before the type */
1588 encode_reflection_type (assembly, fb->type, p, &p);
1589 g_assert (p-buf < 256);
1590 mono_metadata_encode_value (p-buf, b, &b);
1591 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1597 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1598 char blob_size [64];
1599 char *b = blob_size;
1602 guint32 idx = 0, len = 0, dummy = 0;
1604 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1605 guint32 fpa_double [2];
1610 p = buf = g_malloc (64);
1612 *ret_type = MONO_TYPE_CLASS;
1614 box_val = (char*)&dummy;
1616 box_val = ((char*)val) + sizeof (MonoObject);
1617 *ret_type = val->vtable->klass->byval_arg.type;
1620 switch (*ret_type) {
1621 case MONO_TYPE_BOOLEAN:
1626 case MONO_TYPE_CHAR:
1643 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1644 fpa_p = (guint32*)box_val;
1645 fpa_double [0] = fpa_p [1];
1646 fpa_double [1] = fpa_p [0];
1647 box_val = (char*)fpa_double;
1651 case MONO_TYPE_VALUETYPE:
1652 if (val->vtable->klass->enumtype) {
1653 *ret_type = val->vtable->klass->enum_basetype->type;
1656 g_error ("we can't encode valuetypes");
1657 case MONO_TYPE_CLASS:
1659 case MONO_TYPE_STRING: {
1660 MonoString *str = (MonoString*)val;
1661 /* there is no signature */
1662 len = str->length * 2;
1663 mono_metadata_encode_value (len, b, &b);
1664 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1666 char *swapped = g_malloc (2 * mono_string_length (str));
1667 const char *p = (const char*)mono_string_chars (str);
1669 swap_with_size (swapped, p, 2, mono_string_length (str));
1670 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1674 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1681 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1684 /* there is no signature */
1685 mono_metadata_encode_value (len, b, &b);
1686 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1687 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1688 swap_with_size (blob_size, box_val, len, 1);
1689 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1691 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1699 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1700 char blob_size [64];
1701 char *b = blob_size;
1702 char *p, *buf, *str;
1703 guint32 idx, len, bufsize = 256;
1705 p = buf = g_malloc (bufsize);
1707 mono_metadata_encode_value (minfo->type, p, &p);
1709 switch (minfo->type) {
1710 case MONO_NATIVE_BYVALTSTR:
1711 case MONO_NATIVE_BYVALARRAY:
1712 mono_metadata_encode_value (minfo->count, p, &p);
1714 case MONO_NATIVE_LPARRAY:
1715 if (minfo->eltype || minfo->has_size) {
1716 mono_metadata_encode_value (minfo->eltype, p, &p);
1717 if (minfo->has_size) {
1718 if (minfo->param_num != -1)
1719 mono_metadata_encode_value (minfo->param_num, p, &p);
1721 mono_metadata_encode_value (0, p, &p);
1722 if (minfo->count != -1)
1723 mono_metadata_encode_value (minfo->count, p, &p);
1725 mono_metadata_encode_value (0, p, &p);
1727 /* LAMESPEC: ElemMult is undocumented */
1728 if (minfo->param_num != -1)
1729 mono_metadata_encode_value (1, p, &p);
1731 mono_metadata_encode_value (0, p, &p);
1735 case MONO_NATIVE_CUSTOM:
1737 str = mono_string_to_utf8 (minfo->guid);
1739 mono_metadata_encode_value (len, p, &p);
1740 memcpy (p, str, len);
1744 mono_metadata_encode_value (0, p, &p);
1746 /* native type name */
1747 mono_metadata_encode_value (0, p, &p);
1748 /* custom marshaler type name */
1749 if (minfo->marshaltype || minfo->marshaltyperef) {
1750 if (minfo->marshaltyperef)
1751 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1753 str = mono_string_to_utf8 (minfo->marshaltype);
1755 mono_metadata_encode_value (len, p, &p);
1756 if (p + len >= buf + bufsize) {
1759 buf = g_realloc (buf, bufsize);
1762 memcpy (p, str, len);
1766 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1767 mono_metadata_encode_value (0, p, &p);
1769 if (minfo->mcookie) {
1770 str = mono_string_to_utf8 (minfo->mcookie);
1772 mono_metadata_encode_value (len, p, &p);
1773 if (p + len >= buf + bufsize) {
1776 buf = g_realloc (buf, bufsize);
1779 memcpy (p, str, len);
1783 mono_metadata_encode_value (0, p, &p);
1790 mono_metadata_encode_value (len, b, &b);
1791 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1797 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1799 MonoDynamicTable *table;
1803 /* maybe this fixup should be done in the C# code */
1804 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1805 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1806 table = &assembly->tables [MONO_TABLE_FIELD];
1807 fb->table_idx = table->next_idx ++;
1808 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1809 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1810 name = mono_string_to_utf8 (fb->name);
1811 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1813 values [MONO_FIELD_FLAGS] = fb->attrs;
1814 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1816 if (fb->offset != -1) {
1817 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1819 alloc_table (table, table->rows);
1820 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1821 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1822 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1824 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1825 guint32 field_type = 0;
1826 table = &assembly->tables [MONO_TABLE_CONSTANT];
1828 alloc_table (table, table->rows);
1829 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1830 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1831 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1832 values [MONO_CONSTANT_TYPE] = field_type;
1833 values [MONO_CONSTANT_PADDING] = 0;
1835 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1837 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1839 alloc_table (table, table->rows);
1840 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1841 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1843 * We store it in the code section because it's simpler for now.
1846 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1848 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1849 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1851 if (fb->marshal_info) {
1852 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1854 alloc_table (table, table->rows);
1855 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1856 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1857 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1862 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1866 char *b = blob_size;
1867 guint32 nparams = 0;
1868 MonoReflectionMethodBuilder *mb = fb->get_method;
1869 MonoReflectionMethodBuilder *smb = fb->set_method;
1870 guint32 idx, i, size;
1872 if (mb && mb->parameters)
1873 nparams = mono_array_length (mb->parameters);
1874 if (!mb && smb && smb->parameters)
1875 nparams = mono_array_length (smb->parameters) - 1;
1876 size = 24 + nparams * 10;
1877 buf = p = g_malloc (size);
1880 mono_metadata_encode_value (nparams, p, &p);
1882 encode_reflection_type (assembly, mb->rtype, p, &p);
1883 for (i = 0; i < nparams; ++i) {
1884 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1885 encode_reflection_type (assembly, pt, p, &p);
1888 /* the property type is the last param */
1889 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1890 for (i = 0; i < nparams; ++i) {
1891 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1892 encode_reflection_type (assembly, pt, p, &p);
1896 encode_reflection_type (assembly, fb->type, p, &p);
1900 g_assert (p - buf < size);
1901 mono_metadata_encode_value (p-buf, b, &b);
1902 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1908 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1910 MonoDynamicTable *table;
1913 guint num_methods = 0;
1917 * we need to set things in the following tables:
1918 * PROPERTYMAP (info already filled in _get_type_info ())
1919 * PROPERTY (rows already preallocated in _get_type_info ())
1920 * METHOD (method info already done with the generic method code)
1923 table = &assembly->tables [MONO_TABLE_PROPERTY];
1924 pb->table_idx = table->next_idx ++;
1925 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1926 name = mono_string_to_utf8 (pb->name);
1927 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1929 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1930 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1932 /* FIXME: we still don't handle 'other' methods */
1933 if (pb->get_method) num_methods ++;
1934 if (pb->set_method) num_methods ++;
1936 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1937 table->rows += num_methods;
1938 alloc_table (table, table->rows);
1940 if (pb->get_method) {
1941 semaidx = table->next_idx ++;
1942 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1943 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1944 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1945 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1947 if (pb->set_method) {
1948 semaidx = table->next_idx ++;
1949 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1950 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1951 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1952 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1957 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1959 MonoDynamicTable *table;
1962 guint num_methods = 0;
1966 * we need to set things in the following tables:
1967 * EVENTMAP (info already filled in _get_type_info ())
1968 * EVENT (rows already preallocated in _get_type_info ())
1969 * METHOD (method info already done with the generic method code)
1972 table = &assembly->tables [MONO_TABLE_EVENT];
1973 eb->table_idx = table->next_idx ++;
1974 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1975 name = mono_string_to_utf8 (eb->name);
1976 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1978 values [MONO_EVENT_FLAGS] = eb->attrs;
1979 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1982 * FIXME: we still don't handle 'other' methods
1984 if (eb->add_method) num_methods ++;
1985 if (eb->remove_method) num_methods ++;
1986 if (eb->raise_method) num_methods ++;
1988 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1989 table->rows += num_methods;
1990 alloc_table (table, table->rows);
1992 if (eb->add_method) {
1993 semaidx = table->next_idx ++;
1994 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1995 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1996 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1997 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1999 if (eb->remove_method) {
2000 semaidx = table->next_idx ++;
2001 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2002 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2003 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2004 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2006 if (eb->raise_method) {
2007 semaidx = table->next_idx ++;
2008 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2009 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2010 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2011 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2016 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2018 MonoDynamicTable *table;
2019 guint32 num_constraints, i;
2023 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2024 num_constraints = gparam->iface_constraints ?
2025 mono_array_length (gparam->iface_constraints) : 0;
2026 table->rows += num_constraints;
2027 if (gparam->base_type)
2029 alloc_table (table, table->rows);
2031 if (gparam->base_type) {
2032 table_idx = table->next_idx ++;
2033 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2035 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2036 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2037 assembly, gparam->base_type->type);
2040 for (i = 0; i < num_constraints; i++) {
2041 MonoReflectionType *constraint = mono_array_get (
2042 gparam->iface_constraints, gpointer, i);
2044 table_idx = table->next_idx ++;
2045 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2047 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2048 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2049 assembly, constraint->type);
2054 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2056 GenericParamTableEntry *entry;
2059 * The GenericParam table must be sorted according to the `owner' field.
2060 * We need to do this sorting prior to writing the GenericParamConstraint
2061 * table, since we have to use the final GenericParam table indices there
2062 * and they must also be sorted.
2065 entry = g_new0 (GenericParamTableEntry, 1);
2066 entry->owner = owner;
2067 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2069 g_ptr_array_add (assembly->gen_params, entry);
2073 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2075 MonoDynamicTable *table;
2076 MonoGenericParam *param;
2080 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2081 table_idx = table->next_idx ++;
2082 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2084 param = entry->gparam->type.type->data.generic_param;
2086 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2087 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2088 values [MONO_GENERICPARAM_NUMBER] = param->num;
2089 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2091 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2093 encode_constraints (entry->gparam, table_idx, assembly);
2097 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2099 MonoDynamicTable *table;
2102 guint32 cols [MONO_ASSEMBLY_SIZE];
2106 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2109 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2110 table = &assembly->tables [MONO_TABLE_MODULEREF];
2111 token = table->next_idx ++;
2113 alloc_table (table, table->rows);
2114 values = table->values + token * MONO_MODULEREF_SIZE;
2115 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2117 token <<= MONO_RESOLTION_SCOPE_BITS;
2118 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2119 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2124 if (image->assembly->dynamic)
2126 memset (cols, 0, sizeof (cols));
2128 /* image->assembly->image is the manifest module */
2129 image = image->assembly->image;
2130 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2133 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2134 token = table->next_idx ++;
2136 alloc_table (table, table->rows);
2137 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2138 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2139 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2140 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2141 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2142 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2143 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2144 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2145 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2147 if (strcmp ("", image->assembly->aname.culture)) {
2148 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2149 image->assembly->aname.culture);
2152 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2153 guchar pubtoken [9];
2155 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2156 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2158 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2160 token <<= MONO_RESOLTION_SCOPE_BITS;
2161 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2162 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2167 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2169 MonoDynamicTable *table;
2175 char *b = blob_size;
2177 switch (type->type) {
2178 case MONO_TYPE_FNPTR:
2180 case MONO_TYPE_SZARRAY:
2181 case MONO_TYPE_ARRAY:
2183 case MONO_TYPE_MVAR:
2184 case MONO_TYPE_GENERICINST:
2185 encode_type (assembly, type, p, &p);
2187 case MONO_TYPE_CLASS:
2188 case MONO_TYPE_VALUETYPE: {
2189 MonoClass *k = mono_class_from_mono_type (type);
2190 if (!k || !k->generic_class)
2192 encode_generic_class (assembly, k->generic_class, p, &p);
2199 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2200 if (assembly->save) {
2201 g_assert (p-sig < 128);
2202 mono_metadata_encode_value (p-sig, b, &b);
2203 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2204 alloc_table (table, table->rows + 1);
2205 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2206 values [MONO_TYPESPEC_SIGNATURE] = token;
2209 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2210 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2216 * Despite the name, we handle also TypeSpec (with the above helper).
2219 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2221 MonoDynamicTable *table;
2223 guint32 token, scope, enclosing;
2226 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2229 token = create_typespec (assembly, type);
2232 klass = my_mono_class_from_mono_type (type);
2234 klass = mono_class_from_mono_type (type);
2237 * If it's in the same module and not a generic type parameter:
2239 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2240 (type->type != MONO_TYPE_MVAR)) {
2241 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2242 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2243 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2247 if (klass->nested_in) {
2248 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2249 /* get the typeref idx of the enclosing type */
2250 enclosing >>= MONO_TYPEDEFORREF_BITS;
2251 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2253 scope = resolution_scope_from_image (assembly, klass->image);
2255 table = &assembly->tables [MONO_TABLE_TYPEREF];
2256 if (assembly->save) {
2257 alloc_table (table, table->rows + 1);
2258 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2259 values [MONO_TYPEREF_SCOPE] = scope;
2260 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2261 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2263 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2264 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2266 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2271 * Insert a memberef row into the metadata: the token that point to the memberref
2272 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2273 * mono_image_get_fieldref_token()).
2274 * The sig param is an index to an already built signature.
2277 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2279 MonoDynamicTable *table;
2281 guint32 token, pclass;
2284 parent = mono_image_typedef_or_ref (assembly, type);
2285 switch (parent & MONO_TYPEDEFORREF_MASK) {
2286 case MONO_TYPEDEFORREF_TYPEREF:
2287 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2289 case MONO_TYPEDEFORREF_TYPESPEC:
2290 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2292 case MONO_TYPEDEFORREF_TYPEDEF:
2293 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2296 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2299 /* extract the index */
2300 parent >>= MONO_TYPEDEFORREF_BITS;
2302 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2304 if (assembly->save) {
2305 alloc_table (table, table->rows + 1);
2306 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2307 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2308 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2309 values [MONO_MEMBERREF_SIGNATURE] = sig;
2312 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2319 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2322 MonoMethodSignature *sig;
2324 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2329 * A methodref signature can't contain an unmanaged calling convention.
2331 sig = mono_metadata_signature_dup (mono_method_signature (method));
2332 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2333 sig->call_convention = MONO_CALL_DEFAULT;
2334 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2335 method->name, method_encode_signature (assembly, sig));
2337 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2342 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2343 const gchar *name, guint32 sig)
2345 MonoDynamicTable *table;
2349 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2351 if (assembly->save) {
2352 alloc_table (table, table->rows + 1);
2353 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2354 values [MONO_MEMBERREF_CLASS] = original;
2355 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2356 values [MONO_MEMBERREF_SIGNATURE] = sig;
2359 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2366 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2369 ReflectionMethodBuilder rmb;
2371 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2375 reflection_methodbuilder_from_method_builder (&rmb, mb);
2377 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2378 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2379 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2384 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2387 ReflectionMethodBuilder rmb;
2389 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2393 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2395 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2396 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2397 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2402 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2407 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2410 g_assert (f->field->parent);
2411 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2412 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2413 f->field->name, fieldref_encode_signature (assembly, type));
2414 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2419 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2424 guint32 nparams = gmethod->inst->type_argc;
2425 guint32 size = 10 + nparams * 30;
2428 char *b = blob_size;
2430 if (!assembly->save)
2433 p = buf = g_malloc (size);
2435 * FIXME: vararg, explicit_this, differenc call_conv values...
2437 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2438 mono_metadata_encode_value (nparams, p, &p);
2440 for (i = 0; i < nparams; i++)
2441 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2444 g_assert (p - buf < size);
2445 mono_metadata_encode_value (p-buf, b, &b);
2446 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2452 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2454 MonoDynamicTable *table;
2456 guint32 token, mtoken = 0, sig;
2457 MonoMethodInflated *imethod;
2458 MonoMethod *declaring;
2460 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2462 g_assert (method->is_inflated);
2463 method = mono_get_inflated_method (method);
2464 imethod = (MonoMethodInflated *) method;
2465 declaring = imethod->declaring;
2467 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2468 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2470 if (!mono_method_signature (declaring)->generic_param_count)
2473 switch (mono_metadata_token_table (mtoken)) {
2474 case MONO_TABLE_MEMBERREF:
2475 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2477 case MONO_TABLE_METHOD:
2478 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2481 g_assert_not_reached ();
2484 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2486 if (assembly->save) {
2487 alloc_table (table, table->rows + 1);
2488 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2489 values [MONO_METHODSPEC_METHOD] = mtoken;
2490 values [MONO_METHODSPEC_SIGNATURE] = sig;
2493 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2500 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2502 MonoMethodInflated *imethod;
2503 MonoMethod *inflated;
2506 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2510 g_assert (method->is_inflated);
2511 inflated = mono_get_inflated_method (method);
2512 imethod = (MonoMethodInflated *) inflated;
2514 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2515 token = method_encode_methodspec (assembly, inflated);
2517 guint32 sig = method_encode_signature (
2518 assembly, mono_method_signature (imethod->declaring));
2519 token = mono_image_get_memberref_token (
2520 assembly, &inflated->klass->byval_arg, inflated->name, sig);
2523 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2528 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2530 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2533 m = mono_get_inflated_method (m);
2535 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2536 token = mono_image_get_memberref_token (
2537 assembly, &m->klass->byval_arg, m->name, sig);
2543 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2545 MonoDynamicTable *table;
2552 char *b = blob_size;
2556 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2557 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2558 * Because of this, we must not insert it into the `typeref' hash table.
2561 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2565 g_assert (tb->generic_params);
2566 klass = mono_class_from_mono_type (tb->type.type);
2568 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2569 encode_type (assembly, &klass->byval_arg, p, &p);
2571 count = mono_array_length (tb->generic_params);
2572 mono_metadata_encode_value (count, p, &p);
2573 for (i = 0; i < count; i++) {
2574 MonoReflectionGenericParam *gparam;
2576 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2578 encode_type (assembly, gparam->type.type, p, &p);
2581 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2582 g_assert (p-sig < 128);
2584 if (assembly->save) {
2585 mono_metadata_encode_value (p-sig, b, &b);
2586 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2587 alloc_table (table, table->rows + 1);
2588 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2589 values [MONO_TYPESPEC_SIGNATURE] = token;
2592 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2593 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2599 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2601 MonoDynamicTable *table;
2604 guint32 token, pclass, parent, sig;
2607 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2611 klass = mono_class_from_mono_type (fb->typeb->type);
2612 name = mono_string_to_utf8 (fb->name);
2614 sig = fieldref_encode_signature (assembly, fb->type->type);
2616 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2617 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2619 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2620 parent >>= MONO_TYPEDEFORREF_BITS;
2622 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2624 if (assembly->save) {
2625 alloc_table (table, table->rows + 1);
2626 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2627 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2628 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2629 values [MONO_MEMBERREF_SIGNATURE] = sig;
2632 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2634 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2639 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2647 char *b = blob_size;
2649 if (!assembly->save)
2653 g_assert (helper->type == 2);
2655 if (helper->arguments)
2656 nargs = mono_array_length (helper->arguments);
2660 size = 10 + (nargs * 10);
2662 p = buf = g_malloc (size);
2664 /* Encode calling convention */
2665 /* Change Any to Standard */
2666 if ((helper->call_conv & 0x03) == 0x03)
2667 helper->call_conv = 0x01;
2668 /* explicit_this implies has_this */
2669 if (helper->call_conv & 0x40)
2670 helper->call_conv &= 0x20;
2672 if (helper->call_conv == 0) { /* Unmanaged */
2673 *p = helper->unmanaged_call_conv - 1;
2676 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2677 if (helper->call_conv & 0x02) /* varargs */
2682 mono_metadata_encode_value (nargs, p, &p);
2683 encode_reflection_type (assembly, helper->return_type, p, &p);
2684 for (i = 0; i < nargs; ++i) {
2685 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2686 encode_reflection_type (assembly, pt, p, &p);
2689 g_assert (p - buf < size);
2690 mono_metadata_encode_value (p-buf, b, &b);
2691 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2698 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2701 MonoDynamicTable *table;
2704 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2705 idx = table->next_idx ++;
2707 alloc_table (table, table->rows);
2708 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2710 values [MONO_STAND_ALONE_SIGNATURE] =
2711 mono_reflection_encode_sighelper (assembly, helper);
2717 reflection_cc_to_file (int call_conv) {
2718 switch (call_conv & 0x3) {
2720 case 1: return MONO_CALL_DEFAULT;
2721 case 2: return MONO_CALL_VARARG;
2723 g_assert_not_reached ();
2730 MonoMethodSignature *sig;
2736 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2741 MonoMethodSignature *sig;
2744 name = mono_string_to_utf8 (m->name);
2745 nparams = mono_array_length (m->parameters);
2746 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2748 sig->sentinelpos = -1;
2749 sig->call_convention = reflection_cc_to_file (m->call_conv);
2750 sig->param_count = nparams;
2751 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2752 for (i = 0; i < nparams; ++i) {
2753 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2754 sig->params [i] = t->type;
2757 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2759 if (strcmp (name, am->name) == 0 &&
2760 mono_metadata_type_equal (am->parent, m->parent->type) &&
2761 mono_metadata_signature_equal (am->sig, sig)) {
2764 m->table_idx = am->token & 0xffffff;
2768 am = g_new0 (ArrayMethod, 1);
2771 am->parent = m->parent->type;
2772 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2773 method_encode_signature (assembly, sig));
2774 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2775 m->table_idx = am->token & 0xffffff;
2780 * Insert into the metadata tables all the info about the TypeBuilder tb.
2781 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2784 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2786 MonoDynamicTable *table;
2788 int i, is_object = 0, is_system = 0;
2791 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2792 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2793 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2794 n = mono_string_to_utf8 (tb->name);
2795 if (strcmp (n, "Object") == 0)
2797 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2799 n = mono_string_to_utf8 (tb->nspace);
2800 if (strcmp (n, "System") == 0)
2802 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2804 if (tb->parent && !(is_system && is_object) &&
2805 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2806 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2808 values [MONO_TYPEDEF_EXTENDS] = 0;
2810 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2811 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2814 * if we have explicitlayout or sequentiallayouts, output data in the
2815 * ClassLayout table.
2817 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2818 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2819 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2821 alloc_table (table, table->rows);
2822 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2823 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2824 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2825 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2828 /* handle interfaces */
2829 if (tb->interfaces) {
2830 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2832 table->rows += mono_array_length (tb->interfaces);
2833 alloc_table (table, table->rows);
2834 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2835 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2836 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2837 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2838 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2839 values += MONO_INTERFACEIMPL_SIZE;
2845 table = &assembly->tables [MONO_TABLE_FIELD];
2846 table->rows += tb->num_fields;
2847 alloc_table (table, table->rows);
2848 for (i = 0; i < tb->num_fields; ++i)
2849 mono_image_get_field_info (
2850 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2853 /* handle constructors */
2855 table = &assembly->tables [MONO_TABLE_METHOD];
2856 table->rows += mono_array_length (tb->ctors);
2857 alloc_table (table, table->rows);
2858 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2859 mono_image_get_ctor_info (domain,
2860 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2863 /* handle methods */
2865 table = &assembly->tables [MONO_TABLE_METHOD];
2866 table->rows += tb->num_methods;
2867 alloc_table (table, table->rows);
2868 for (i = 0; i < tb->num_methods; ++i)
2869 mono_image_get_method_info (
2870 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2873 /* Do the same with properties etc.. */
2874 if (tb->events && mono_array_length (tb->events)) {
2875 table = &assembly->tables [MONO_TABLE_EVENT];
2876 table->rows += mono_array_length (tb->events);
2877 alloc_table (table, table->rows);
2878 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2880 alloc_table (table, table->rows);
2881 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2882 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2883 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2884 for (i = 0; i < mono_array_length (tb->events); ++i)
2885 mono_image_get_event_info (
2886 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2888 if (tb->properties && mono_array_length (tb->properties)) {
2889 table = &assembly->tables [MONO_TABLE_PROPERTY];
2890 table->rows += mono_array_length (tb->properties);
2891 alloc_table (table, table->rows);
2892 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2894 alloc_table (table, table->rows);
2895 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2896 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2897 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2898 for (i = 0; i < mono_array_length (tb->properties); ++i)
2899 mono_image_get_property_info (
2900 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2903 /* handle generic parameters */
2904 if (tb->generic_params) {
2905 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2906 table->rows += mono_array_length (tb->generic_params);
2907 alloc_table (table, table->rows);
2908 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2909 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2911 mono_image_get_generic_param_info (
2912 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2916 mono_image_add_decl_security (assembly,
2917 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2920 MonoDynamicTable *ntable;
2922 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2923 ntable->rows += mono_array_length (tb->subtypes);
2924 alloc_table (ntable, ntable->rows);
2925 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2927 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2928 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2930 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2931 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2932 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2933 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2934 mono_string_to_utf8 (tb->name), tb->table_idx,
2935 ntable->next_idx, ntable->rows);*/
2936 values += MONO_NESTED_CLASS_SIZE;
2943 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2947 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2949 if (!type->subtypes)
2952 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2953 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2954 collect_types (types, subtype);
2959 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2961 if ((*type1)->table_idx < (*type2)->table_idx)
2964 if ((*type1)->table_idx > (*type2)->table_idx)
2971 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2976 for (i = 0; i < mono_array_length (pinfo); ++i) {
2977 MonoReflectionParamBuilder *pb;
2978 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2981 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2986 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2989 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2991 for (i = 0; i < tb->num_fields; ++i) {
2992 MonoReflectionFieldBuilder* fb;
2993 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2994 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2998 for (i = 0; i < mono_array_length (tb->events); ++i) {
2999 MonoReflectionEventBuilder* eb;
3000 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3001 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3004 if (tb->properties) {
3005 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3006 MonoReflectionPropertyBuilder* pb;
3007 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3008 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3012 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3013 MonoReflectionCtorBuilder* cb;
3014 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3015 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3016 params_add_cattrs (assembly, cb->pinfo);
3021 for (i = 0; i < tb->num_methods; ++i) {
3022 MonoReflectionMethodBuilder* mb;
3023 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3024 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3025 params_add_cattrs (assembly, mb->pinfo);
3030 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3031 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3036 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3040 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3042 if (moduleb->global_methods) {
3043 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3044 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3045 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3046 params_add_cattrs (assembly, mb->pinfo);
3050 if (moduleb->global_fields) {
3051 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3052 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3053 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3057 if (moduleb->types) {
3058 for (i = 0; i < moduleb->num_types; ++i)
3059 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3064 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3066 MonoDynamicTable *table;
3070 char *b = blob_size;
3073 table = &assembly->tables [MONO_TABLE_FILE];
3075 alloc_table (table, table->rows);
3076 values = table->values + table->next_idx * MONO_FILE_SIZE;
3077 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3078 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3079 if (module->image->dynamic) {
3080 /* This depends on the fact that the main module is emitted last */
3081 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3082 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3085 path = g_strdup (module->image->name);
3087 mono_sha1_get_digest_from_file (path, hash);
3090 mono_metadata_encode_value (20, b, &b);
3091 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3092 mono_image_add_stream_data (&assembly->blob, hash, 20);
3097 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3099 MonoDynamicTable *table;
3103 table = &assembly->tables [MONO_TABLE_MODULE];
3104 mb->table_idx = table->next_idx ++;
3105 name = mono_string_to_utf8 (mb->module.name);
3106 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3108 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3111 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3112 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3113 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3114 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3118 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3119 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3121 MonoDynamicTable *table;
3125 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3126 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3129 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3131 alloc_table (table, table->rows);
3132 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3134 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3135 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3136 if (klass->nested_in)
3137 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3139 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3140 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3141 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3143 res = table->next_idx;
3147 /* Emit nested types */
3148 if (klass->nested_classes) {
3151 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3152 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3159 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3160 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3165 klass = mono_class_from_mono_type (tb->type.type);
3167 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3169 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3170 parent_index, assembly);
3174 * We need to do this ourselves since klass->nested_classes is not set up.
3177 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3178 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3183 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3184 guint32 module_index, MonoDynamicImage *assembly)
3186 MonoImage *image = module->image;
3190 t = &image->tables [MONO_TABLE_TYPEDEF];
3192 for (i = 0; i < t->rows; ++i) {
3193 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3195 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3196 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3201 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3203 MonoDynamicTable *table;
3209 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3211 if (assemblyb->type_forwarders) {
3212 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3213 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3219 klass = mono_class_from_mono_type (t->type);
3221 scope = resolution_scope_from_image (assembly, klass->image);
3222 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3223 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3226 alloc_table (table, table->rows);
3227 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3229 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3230 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3231 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3232 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3233 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3238 #define align_pointer(base,p)\
3240 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3242 (p) += 4 - (__diff & 3);\
3246 compare_constants (const void *a, const void *b)
3248 const guint32 *a_values = a;
3249 const guint32 *b_values = b;
3250 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3254 compare_semantics (const void *a, const void *b)
3256 const guint32 *a_values = a;
3257 const guint32 *b_values = b;
3258 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3261 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3265 compare_custom_attrs (const void *a, const void *b)
3267 const guint32 *a_values = a;
3268 const guint32 *b_values = b;
3270 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3274 compare_field_marshal (const void *a, const void *b)
3276 const guint32 *a_values = a;
3277 const guint32 *b_values = b;
3279 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3283 compare_nested (const void *a, const void *b)
3285 const guint32 *a_values = a;
3286 const guint32 *b_values = b;
3288 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3292 compare_genericparam (const void *a, const void *b)
3294 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3295 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3297 if ((*b_entry)->owner == (*a_entry)->owner)
3299 (*a_entry)->gparam->type.type->data.generic_param->num -
3300 (*b_entry)->gparam->type.type->data.generic_param->num;
3302 return (*a_entry)->owner - (*b_entry)->owner;
3306 compare_declsecurity_attrs (const void *a, const void *b)
3308 const guint32 *a_values = a;
3309 const guint32 *b_values = b;
3311 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3315 pad_heap (MonoDynamicStream *sh)
3317 if (sh->index & 3) {
3318 int sz = 4 - (sh->index & 3);
3319 memset (sh->data + sh->index, 0, sz);
3326 MonoDynamicStream *stream;
3330 * build_compressed_metadata() fills in the blob of data that represents the
3331 * raw metadata as it will be saved in the PE file. The five streams are output
3332 * and the metadata tables are comnpressed from the guint32 array representation,
3333 * to the compressed on-disk format.
3336 build_compressed_metadata (MonoDynamicImage *assembly)
3338 MonoDynamicTable *table;
3340 guint64 valid_mask = 0;
3341 guint64 sorted_mask;
3342 guint32 heapt_size = 0;
3343 guint32 meta_size = 256; /* allow for header and other stuff */
3344 guint32 table_offset;
3345 guint32 ntables = 0;
3351 struct StreamDesc stream_desc [5];
3353 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3354 for (i = 0; i < assembly->gen_params->len; i++){
3355 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3356 write_generic_param_entry (assembly, entry);
3359 stream_desc [0].name = "#~";
3360 stream_desc [0].stream = &assembly->tstream;
3361 stream_desc [1].name = "#Strings";
3362 stream_desc [1].stream = &assembly->sheap;
3363 stream_desc [2].name = "#US";
3364 stream_desc [2].stream = &assembly->us;
3365 stream_desc [3].name = "#Blob";
3366 stream_desc [3].stream = &assembly->blob;
3367 stream_desc [4].name = "#GUID";
3368 stream_desc [4].stream = &assembly->guid;
3370 /* tables that are sorted */
3371 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3372 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3373 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3374 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3375 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3376 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3378 /* Compute table sizes */
3379 /* the MonoImage has already been created in mono_image_basic_init() */
3380 meta = &assembly->image;
3382 /* sizes should be multiple of 4 */
3383 pad_heap (&assembly->blob);
3384 pad_heap (&assembly->guid);
3385 pad_heap (&assembly->sheap);
3386 pad_heap (&assembly->us);
3388 /* Setup the info used by compute_sizes () */
3389 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3390 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3391 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3393 meta_size += assembly->blob.index;
3394 meta_size += assembly->guid.index;
3395 meta_size += assembly->sheap.index;
3396 meta_size += assembly->us.index;
3398 for (i=0; i < MONO_TABLE_NUM; ++i)
3399 meta->tables [i].rows = assembly->tables [i].rows;
3401 for (i = 0; i < MONO_TABLE_NUM; i++){
3402 if (meta->tables [i].rows == 0)
3404 valid_mask |= (guint64)1 << i;
3406 meta->tables [i].row_size = mono_metadata_compute_size (
3407 meta, i, &meta->tables [i].size_bitfield);
3408 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3410 heapt_size += 24; /* #~ header size */
3411 heapt_size += ntables * 4;
3412 /* make multiple of 4 */
3415 meta_size += heapt_size;
3416 meta->raw_metadata = g_malloc0 (meta_size);
3417 p = meta->raw_metadata;
3418 /* the metadata signature */
3419 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3420 /* version numbers and 4 bytes reserved */
3421 int16val = (guint16*)p;
3422 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3423 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3425 /* version string */
3426 int32val = (guint32*)p;
3427 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3429 memcpy (p, meta->version, strlen (meta->version));
3430 p += GUINT32_FROM_LE (*int32val);
3431 align_pointer (meta->raw_metadata, p);
3432 int16val = (guint16*)p;
3433 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3434 *int16val = GUINT16_TO_LE (5); /* number of streams */
3438 * write the stream info.
3440 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3441 table_offset += 3; table_offset &= ~3;
3443 assembly->tstream.index = heapt_size;
3444 for (i = 0; i < 5; ++i) {
3445 int32val = (guint32*)p;
3446 stream_desc [i].stream->offset = table_offset;
3447 *int32val++ = GUINT32_TO_LE (table_offset);
3448 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3449 table_offset += GUINT32_FROM_LE (*int32val);
3450 table_offset += 3; table_offset &= ~3;
3452 strcpy (p, stream_desc [i].name);
3453 p += strlen (stream_desc [i].name) + 1;
3454 align_pointer (meta->raw_metadata, p);
3457 * now copy the data, the table stream header and contents goes first.
3459 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3460 p = meta->raw_metadata + assembly->tstream.offset;
3461 int32val = (guint32*)p;
3462 *int32val = GUINT32_TO_LE (0); /* reserved */
3465 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3466 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3467 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3468 *p++ = 2; /* version */
3471 *p++ = 1; /* version */
3475 if (meta->idx_string_wide)
3477 if (meta->idx_guid_wide)
3479 if (meta->idx_blob_wide)
3482 *p++ = 1; /* reserved */
3483 int64val = (guint64*)p;
3484 *int64val++ = GUINT64_TO_LE (valid_mask);
3485 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3487 int32val = (guint32*)p;
3488 for (i = 0; i < MONO_TABLE_NUM; i++){
3489 if (meta->tables [i].rows == 0)
3491 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3493 p = (unsigned char*)int32val;
3495 /* sort the tables that still need sorting */
3496 table = &assembly->tables [MONO_TABLE_CONSTANT];
3498 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3499 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3501 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3502 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3504 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3505 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3507 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3508 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3510 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3511 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3512 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3514 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3516 /* compress the tables */
3517 for (i = 0; i < MONO_TABLE_NUM; i++){
3520 guint32 bitfield = meta->tables [i].size_bitfield;
3521 if (!meta->tables [i].rows)
3523 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3524 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3525 meta->tables [i].base = p;
3526 for (row = 1; row <= meta->tables [i].rows; ++row) {
3527 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3528 for (col = 0; col < assembly->tables [i].columns; ++col) {
3529 switch (mono_metadata_table_size (bitfield, col)) {
3531 *p++ = values [col];
3534 *p++ = values [col] & 0xff;
3535 *p++ = (values [col] >> 8) & 0xff;
3538 *p++ = values [col] & 0xff;
3539 *p++ = (values [col] >> 8) & 0xff;
3540 *p++ = (values [col] >> 16) & 0xff;
3541 *p++ = (values [col] >> 24) & 0xff;
3544 g_assert_not_reached ();
3548 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3551 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3552 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3553 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3554 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3555 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3557 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3561 * Some tables in metadata need to be sorted according to some criteria, but
3562 * when methods and fields are first created with reflection, they may be assigned a token
3563 * that doesn't correspond to the final token they will get assigned after the sorting.
3564 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3565 * with the reflection objects that represent them. Once all the tables are set up, the
3566 * reflection objects will contains the correct table index. fixup_method() will fixup the
3567 * tokens for the method with ILGenerator @ilgen.
3570 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3571 guint32 code_idx = GPOINTER_TO_UINT (value);
3572 MonoReflectionILTokenInfo *iltoken;
3573 MonoReflectionFieldBuilder *field;
3574 MonoReflectionCtorBuilder *ctor;
3575 MonoReflectionMethodBuilder *method;
3576 MonoReflectionTypeBuilder *tb;
3577 MonoReflectionArrayMethod *am;
3579 unsigned char *target;
3581 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3582 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3583 target = assembly->code.data + code_idx + iltoken->code_pos;
3584 switch (target [3]) {
3585 case MONO_TABLE_FIELD:
3586 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3587 field = (MonoReflectionFieldBuilder *)iltoken->member;
3588 idx = field->table_idx;
3589 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3590 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3591 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3593 g_assert_not_reached ();
3596 case MONO_TABLE_METHOD:
3597 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3598 method = (MonoReflectionMethodBuilder *)iltoken->member;
3599 idx = method->table_idx;
3600 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3601 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3602 idx = ctor->table_idx;
3603 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3604 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3605 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3606 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3608 g_assert_not_reached ();
3611 case MONO_TABLE_TYPEDEF:
3612 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3613 g_assert_not_reached ();
3614 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3615 idx = tb->table_idx;
3617 case MONO_TABLE_MEMBERREF:
3618 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3619 am = (MonoReflectionArrayMethod*)iltoken->member;
3620 idx = am->table_idx;
3621 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3622 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3623 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3624 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3625 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3626 g_assert (m->klass->generic_class || m->klass->generic_container);
3628 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3630 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3631 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3632 g_assert (f->generic_info);
3634 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3637 g_assert_not_reached ();
3640 case MONO_TABLE_METHODSPEC:
3641 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3642 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3643 g_assert (mono_method_signature (m)->generic_param_count);
3646 g_assert_not_reached ();
3650 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3652 target [0] = idx & 0xff;
3653 target [1] = (idx >> 8) & 0xff;
3654 target [2] = (idx >> 16) & 0xff;
3661 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3662 * value is not known when the table is emitted.
3665 fixup_cattrs (MonoDynamicImage *assembly)
3667 MonoDynamicTable *table;
3669 guint32 type, i, idx, token;
3672 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3674 for (i = 0; i < table->rows; ++i) {
3675 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3677 type = values [MONO_CUSTOM_ATTR_TYPE];
3678 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3679 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3680 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3681 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3684 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3685 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3686 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3687 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3696 * The METHODIMPL table might contain METHODDEF tokens whose final
3697 * value is not known when the table is emitted.
3700 fixup_methodimpl (MonoDynamicImage *assembly)
3702 MonoDynamicTable *table;
3704 guint32 decl, i, idx, token;
3707 table = &assembly->tables [MONO_TABLE_METHODIMPL];
3709 for (i = 0; i < table->rows; ++i) {
3710 values = table->values + ((i + 1) * MONO_METHODIMPL_SIZE);
3711 decl = values [MONO_METHODIMPL_DECLARATION];
3713 idx = decl >> MONO_METHODDEFORREF_BITS;
3714 if ((decl & MONO_METHODDEFORREF_MASK) != MONO_METHODDEFORREF_METHODDEF)
3717 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3718 method = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3721 if (!strcmp (method->vtable->klass->name, "MethodBuilder")) {
3722 token = mono_image_create_token (assembly, method, FALSE);
3723 idx = mono_metadata_token_index (token);
3724 values [MONO_METHODIMPL_DECLARATION] = (idx << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3730 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3732 MonoDynamicTable *table;
3736 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3738 alloc_table (table, table->rows);
3739 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3740 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3741 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3742 name = mono_string_to_utf8 (rsrc->name);
3743 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3745 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3750 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3752 MonoDynamicTable *table;
3756 char *b = blob_size;
3758 guint32 idx, offset;
3760 if (rsrc->filename) {
3761 name = mono_string_to_utf8 (rsrc->filename);
3762 sname = g_path_get_basename (name);
3764 table = &assembly->tables [MONO_TABLE_FILE];
3766 alloc_table (table, table->rows);
3767 values = table->values + table->next_idx * MONO_FILE_SIZE;
3768 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3769 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3772 mono_sha1_get_digest_from_file (name, hash);
3773 mono_metadata_encode_value (20, b, &b);
3774 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3775 mono_image_add_stream_data (&assembly->blob, hash, 20);
3777 idx = table->next_idx++;
3779 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3782 offset = mono_array_length (rsrc->data);
3783 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3784 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3785 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3786 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3790 * The entry should be emitted into the MANIFESTRESOURCE table of
3791 * the main module, but that needs to reference the FILE table
3792 * which isn't emitted yet.
3799 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3803 set_version_from_string (MonoString *version, guint32 *values)
3805 gchar *ver, *p, *str;
3808 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3809 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3810 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3811 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3814 ver = str = mono_string_to_utf8 (version);
3815 for (i = 0; i < 4; ++i) {
3816 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3822 /* handle Revision and Build */
3832 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3836 char *b = blob_size;
3841 len = mono_array_length (pkey);
3842 mono_metadata_encode_value (len, b, &b);
3843 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3844 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3846 /* Special case: check for ECMA key (16 bytes) */
3847 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, guint8, 0), len)) {
3848 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3849 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3850 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3851 /* minimum key size (in 2.0) is 384 bits */
3852 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3854 /* FIXME - verifier */
3855 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3856 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3858 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3864 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3866 MonoDynamicTable *table;
3867 MonoDynamicImage *assembly;
3868 MonoReflectionAssemblyBuilder *assemblyb;
3873 guint32 module_index;
3875 assemblyb = moduleb->assemblyb;
3876 assembly = moduleb->dynamic_image;
3877 domain = mono_object_domain (assemblyb);
3879 /* Emit ASSEMBLY table */
3880 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3881 alloc_table (table, 1);
3882 values = table->values + MONO_ASSEMBLY_SIZE;
3883 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3884 name = mono_string_to_utf8 (assemblyb->name);
3885 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3887 if (assemblyb->culture) {
3888 name = mono_string_to_utf8 (assemblyb->culture);
3889 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3892 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3894 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3895 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3896 set_version_from_string (assemblyb->version, values);
3898 /* Emit FILE + EXPORTED_TYPE table */
3900 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3902 MonoReflectionModuleBuilder *file_module =
3903 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3904 if (file_module != moduleb) {
3905 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3907 if (file_module->types) {
3908 for (j = 0; j < file_module->num_types; ++j) {
3909 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3910 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3915 if (assemblyb->loaded_modules) {
3916 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3917 MonoReflectionModule *file_module =
3918 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3919 mono_image_fill_file_table (domain, file_module, assembly);
3921 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3924 if (assemblyb->type_forwarders)
3925 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3927 /* Emit MANIFESTRESOURCE table */
3929 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3931 MonoReflectionModuleBuilder *file_module =
3932 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3933 /* The table for the main module is emitted later */
3934 if (file_module != moduleb) {
3936 if (file_module->resources) {
3937 int len = mono_array_length (file_module->resources);
3938 for (j = 0; j < len; ++j) {
3939 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3940 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3948 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3949 * for the modulebuilder @moduleb.
3950 * At the end of the process, method and field tokens are fixed up and the
3951 * on-disk compressed metadata representation is created.
3954 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3956 MonoDynamicTable *table;
3957 MonoDynamicImage *assembly;
3958 MonoReflectionAssemblyBuilder *assemblyb;
3963 assemblyb = moduleb->assemblyb;
3964 assembly = moduleb->dynamic_image;
3965 domain = mono_object_domain (assemblyb);
3967 if (assembly->text_rva)
3970 assembly->text_rva = START_TEXT_RVA;
3972 if (moduleb->is_main) {
3973 mono_image_emit_manifest (moduleb);
3976 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3977 table->rows = 1; /* .<Module> */
3979 alloc_table (table, table->rows);
3981 * Set the first entry.
3983 values = table->values + table->columns;
3984 values [MONO_TYPEDEF_FLAGS] = 0;
3985 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3986 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3987 values [MONO_TYPEDEF_EXTENDS] = 0;
3988 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3989 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3992 * handle global methods
3993 * FIXME: test what to do when global methods are defined in multiple modules.
3995 if (moduleb->global_methods) {
3996 table = &assembly->tables [MONO_TABLE_METHOD];
3997 table->rows += mono_array_length (moduleb->global_methods);
3998 alloc_table (table, table->rows);
3999 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4000 mono_image_get_method_info (
4001 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4003 if (moduleb->global_fields) {
4004 table = &assembly->tables [MONO_TABLE_FIELD];
4005 table->rows += mono_array_length (moduleb->global_fields);
4006 alloc_table (table, table->rows);
4007 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4008 mono_image_get_field_info (
4009 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4012 table = &assembly->tables [MONO_TABLE_MODULE];
4013 alloc_table (table, 1);
4014 mono_image_fill_module_table (domain, moduleb, assembly);
4018 /* Collect all types into a list sorted by their table_idx */
4019 GPtrArray *types = g_ptr_array_new ();
4022 for (i = 0; i < moduleb->num_types; ++i) {
4023 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4024 collect_types (types, type);
4027 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4028 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4029 table->rows += types->len;
4030 alloc_table (table, table->rows);
4033 * Emit type names + namespaces at one place inside the string heap,
4034 * so load_class_names () needs to touch fewer pages.
4036 for (i = 0; i < types->len; ++i) {
4037 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4040 n = mono_string_to_utf8 (tb->nspace);
4041 string_heap_insert (&assembly->sheap, n);
4044 for (i = 0; i < types->len; ++i) {
4045 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4048 n = mono_string_to_utf8 (tb->name);
4049 string_heap_insert (&assembly->sheap, n);
4053 for (i = 0; i < types->len; ++i) {
4054 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4055 mono_image_get_type_info (domain, type, assembly);
4057 g_ptr_array_free (types, TRUE);
4061 * table->rows is already set above and in mono_image_fill_module_table.
4063 /* add all the custom attributes at the end, once all the indexes are stable */
4064 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4066 /* CAS assembly permissions */
4067 if (assemblyb->permissions_minimum)
4068 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4069 if (assemblyb->permissions_optional)
4070 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4071 if (assemblyb->permissions_refused)
4072 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4074 module_add_cattrs (assembly, moduleb);
4077 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4078 fixup_cattrs (assembly);
4079 fixup_methodimpl (assembly);
4083 * mono_image_insert_string:
4084 * @module: module builder object
4087 * Insert @str into the user string stream of @module.
4090 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4092 MonoDynamicImage *assembly;
4097 MONO_ARCH_SAVE_REGS;
4099 if (!module->dynamic_image)
4100 mono_image_module_basic_init (module);
4102 assembly = module->dynamic_image;
4104 if (assembly->save) {
4105 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4106 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4107 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4109 char *swapped = g_malloc (2 * mono_string_length (str));
4110 const char *p = (const char*)mono_string_chars (str);
4112 swap_with_size (swapped, p, 2, mono_string_length (str));
4113 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4117 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4119 mono_image_add_stream_data (&assembly->us, "", 1);
4121 idx = assembly->us.index ++;
4124 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4126 return MONO_TOKEN_STRING | idx;
4130 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4135 klass = obj->vtable->klass;
4136 if (strcmp (klass->name, "MonoMethod") == 0) {
4137 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4138 MonoMethodSignature *sig, *old;
4139 guint32 sig_token, parent;
4142 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4144 nargs = mono_array_length (opt_param_types);
4145 old = mono_method_signature (method);
4146 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4148 sig->hasthis = old->hasthis;
4149 sig->explicit_this = old->explicit_this;
4150 sig->call_convention = old->call_convention;
4151 sig->generic_param_count = old->generic_param_count;
4152 sig->param_count = old->param_count + nargs;
4153 sig->sentinelpos = old->param_count;
4154 sig->ret = old->ret;
4156 for (i = 0; i < old->param_count; i++)
4157 sig->params [i] = old->params [i];
4159 for (i = 0; i < nargs; i++) {
4160 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4161 sig->params [old->param_count + i] = rt->type;
4164 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4165 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4166 parent >>= MONO_TYPEDEFORREF_BITS;
4168 parent <<= MONO_MEMBERREF_PARENT_BITS;
4169 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4171 sig_token = method_encode_signature (assembly, sig);
4172 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4173 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4174 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4175 ReflectionMethodBuilder rmb;
4176 guint32 parent, sig;
4178 reflection_methodbuilder_from_method_builder (&rmb, mb);
4179 rmb.opt_types = opt_param_types;
4181 sig = method_builder_encode_signature (assembly, &rmb);
4183 parent = mono_image_create_token (assembly, obj, TRUE);
4184 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4186 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4187 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4189 token = mono_image_get_varargs_method_token (
4190 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4192 g_error ("requested method token for %s\n", klass->name);
4199 * mono_image_create_token:
4200 * @assembly: a dynamic assembly
4203 * Get a token to insert in the IL code stream for the given MemberInfo.
4204 * @obj can be one of:
4205 * ConstructorBuilder
4215 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4220 klass = obj->vtable->klass;
4221 if (strcmp (klass->name, "MethodBuilder") == 0) {
4222 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4224 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4225 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4227 token = mono_image_get_methodbuilder_token (assembly, mb);
4228 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4229 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4230 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4232 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4233 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4235 token = mono_image_get_ctorbuilder_token (assembly, mb);
4236 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4237 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4238 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4239 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4240 if (tb->generic_params) {
4241 token = mono_image_get_generic_field_token (assembly, fb);
4243 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4245 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4246 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4247 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4248 } else if (strcmp (klass->name, "MonoType") == 0 ||
4249 strcmp (klass->name, "GenericTypeParameterBuilder") == 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, "MonoGenericClass") == 0) {
4254 MonoReflectionType *tb = (MonoReflectionType *)obj;
4255 token = mono_metadata_token_from_dor (
4256 mono_image_typedef_or_ref (assembly, tb->type));
4257 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4258 strcmp (klass->name, "MonoMethod") == 0 ||
4259 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4260 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4261 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4262 if (m->method->is_inflated) {
4263 if (create_methodspec)
4264 token = mono_image_get_methodspec_token (assembly, m->method);
4266 token = mono_image_get_inflated_method_token (assembly, m->method);
4267 } else if ((m->method->klass->image == &assembly->image) &&
4268 !m->method->klass->generic_class) {
4269 static guint32 method_table_idx = 0xffffff;
4270 if (m->method->klass->wastypebuilder) {
4271 /* we use the same token as the one that was assigned
4272 * to the Methodbuilder.
4273 * FIXME: do the equivalent for Fields.
4275 token = m->method->token;
4278 * Each token should have a unique index, but the indexes are
4279 * assigned by managed code, so we don't know about them. An
4280 * easy solution is to count backwards...
4282 method_table_idx --;
4283 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4286 token = mono_image_get_methodref_token (assembly, m->method);
4288 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4289 } else if (strcmp (klass->name, "MonoField") == 0) {
4290 MonoReflectionField *f = (MonoReflectionField *)obj;
4291 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4292 static guint32 field_table_idx = 0xffffff;
4294 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4296 token = mono_image_get_fieldref_token (assembly, f);
4298 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4299 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4300 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4301 token = mono_image_get_array_token (assembly, m);
4302 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4303 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4304 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4306 g_error ("requested token for %s\n", klass->name);
4309 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4315 guint32 import_lookup_table;
4319 guint32 import_address_table_rva;
4327 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4329 static MonoDynamicImage*
4330 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4332 static const guchar entrycode [16] = {0xff, 0x25, 0};
4333 MonoDynamicImage *image;
4336 const char *version = mono_get_runtime_info ()->runtime_version;
4339 image = GC_MALLOC (sizeof (MonoDynamicImage));
4341 image = g_new0 (MonoDynamicImage, 1);
4344 /*g_print ("created image %p\n", image);*/
4345 /* keep in sync with image.c */
4346 image->image.name = assembly_name;
4347 image->image.assembly_name = image->image.name; /* they may be different */
4348 image->image.module_name = module_name;
4349 image->image.version = g_strdup (version);
4350 image->image.md_version_major = 1;
4351 image->image.md_version_minor = 1;
4352 image->image.dynamic = TRUE;
4354 image->image.references = g_new0 (MonoAssembly*, 1);
4355 image->image.references [0] = NULL;
4357 mono_image_init (&image->image);
4359 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4360 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4361 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4362 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4363 image->handleref = g_hash_table_new (NULL, NULL);
4364 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4365 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4366 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4367 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4368 image->gen_params = g_ptr_array_new ();
4370 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4371 string_heap_init (&image->sheap);
4372 mono_image_add_stream_data (&image->us, "", 1);
4373 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4374 /* import tables... */
4375 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4376 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4377 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4378 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4379 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4380 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4381 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4382 stream_data_align (&image->code);
4384 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4386 for (i=0; i < MONO_TABLE_NUM; ++i) {
4387 image->tables [i].next_idx = 1;
4388 image->tables [i].columns = table_sizes [i];
4391 image->image.assembly = (MonoAssembly*)assembly;
4392 image->run = assembly->run;
4393 image->save = assembly->save;
4394 image->pe_kind = 0x1; /* ILOnly */
4395 image->machine = 0x14c; /* I386 */
4401 * mono_image_basic_init:
4402 * @assembly: an assembly builder object
4404 * Create the MonoImage that represents the assembly builder and setup some
4405 * of the helper hash table and the basic metadata streams.
4408 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4410 MonoDynamicAssembly *assembly;
4411 MonoDynamicImage *image;
4412 MonoDomain *domain = mono_object_domain (assemblyb);
4414 MONO_ARCH_SAVE_REGS;
4416 if (assemblyb->dynamic_assembly)
4420 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4422 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4425 assembly->assembly.ref_count = 1;
4426 assembly->assembly.dynamic = TRUE;
4427 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4428 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4429 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4430 if (assemblyb->culture)
4431 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4433 assembly->assembly.aname.culture = g_strdup ("");
4435 if (assemblyb->version) {
4436 char *vstr = mono_string_to_utf8 (assemblyb->version);
4437 char **version = g_strsplit (vstr, ".", 4);
4438 char **parts = version;
4439 assembly->assembly.aname.major = atoi (*parts++);
4440 assembly->assembly.aname.minor = atoi (*parts++);
4441 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4442 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4444 g_strfreev (version);
4447 assembly->assembly.aname.major = 0;
4448 assembly->assembly.aname.minor = 0;
4449 assembly->assembly.aname.build = 0;
4450 assembly->assembly.aname.revision = 0;
4453 assembly->run = assemblyb->access != 2;
4454 assembly->save = assemblyb->access != 1;
4456 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4457 image->initial_image = TRUE;
4458 assembly->assembly.aname.name = image->image.name;
4459 assembly->assembly.image = &image->image;
4461 mono_domain_assemblies_lock (domain);
4462 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4463 mono_domain_assemblies_unlock (domain);
4465 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4466 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4470 calc_section_size (MonoDynamicImage *assembly)
4474 /* alignment constraints */
4475 assembly->code.index += 3;
4476 assembly->code.index &= ~3;
4477 assembly->meta_size += 3;
4478 assembly->meta_size &= ~3;
4479 assembly->resources.index += 3;
4480 assembly->resources.index &= ~3;
4482 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4483 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4486 if (assembly->win32_res) {
4487 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4489 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4490 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4494 assembly->sections [MONO_SECTION_RELOC].size = 12;
4495 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4505 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4509 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4511 ResTreeNode *t1 = (ResTreeNode*)a;
4512 ResTreeNode *t2 = (ResTreeNode*)b;
4514 return t1->id - t2->id;
4518 * resource_tree_create:
4520 * Organize the resources into a resource tree.
4522 static ResTreeNode *
4523 resource_tree_create (MonoArray *win32_resources)
4525 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4529 tree = g_new0 (ResTreeNode, 1);
4531 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4532 MonoReflectionWin32Resource *win32_res =
4533 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4537 /* FIXME: BUG: this stores managed references in unmanaged memory */
4538 lang_node = g_new0 (ResTreeNode, 1);
4539 lang_node->id = win32_res->lang_id;
4540 lang_node->win32_res = win32_res;
4542 /* Create type node if neccesary */
4544 for (l = tree->children; l; l = l->next)
4545 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4546 type_node = (ResTreeNode*)l->data;
4551 type_node = g_new0 (ResTreeNode, 1);
4552 type_node->id = win32_res->res_type;
4555 * The resource types have to be sorted otherwise
4556 * Windows Explorer can't display the version information.
4558 tree->children = g_slist_insert_sorted (tree->children,
4559 type_node, resource_tree_compare_by_id);
4562 /* Create res node if neccesary */
4564 for (l = type_node->children; l; l = l->next)
4565 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4566 res_node = (ResTreeNode*)l->data;
4571 res_node = g_new0 (ResTreeNode, 1);
4572 res_node->id = win32_res->res_id;
4573 type_node->children = g_slist_append (type_node->children, res_node);
4576 res_node->children = g_slist_append (res_node->children, lang_node);
4583 * resource_tree_encode:
4585 * Encode the resource tree into the format used in the PE file.
4588 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4591 MonoPEResourceDir dir;
4592 MonoPEResourceDirEntry dir_entry;
4593 MonoPEResourceDataEntry data_entry;
4597 * For the format of the resource directory, see the article
4598 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4602 memset (&dir, 0, sizeof (dir));
4603 memset (&dir_entry, 0, sizeof (dir_entry));
4604 memset (&data_entry, 0, sizeof (data_entry));
4606 g_assert (sizeof (dir) == 16);
4607 g_assert (sizeof (dir_entry) == 8);
4608 g_assert (sizeof (data_entry) == 16);
4610 node->offset = p - begin;
4612 /* IMAGE_RESOURCE_DIRECTORY */
4613 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4615 memcpy (p, &dir, sizeof (dir));
4618 /* Reserve space for entries */
4620 p += sizeof (dir_entry) * dir.res_id_entries;
4622 /* Write children */
4623 for (l = node->children; l; l = l->next) {
4624 ResTreeNode *child = (ResTreeNode*)l->data;
4626 if (child->win32_res) {
4628 child->offset = p - begin;
4630 /* IMAGE_RESOURCE_DATA_ENTRY */
4631 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4632 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4634 memcpy (p, &data_entry, sizeof (data_entry));
4635 p += sizeof (data_entry);
4637 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4638 p += data_entry.rde_size;
4640 resource_tree_encode (child, begin, p, &p);
4644 /* IMAGE_RESOURCE_ENTRY */
4645 for (l = node->children; l; l = l->next) {
4646 ResTreeNode *child = (ResTreeNode*)l->data;
4647 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4649 dir_entry.is_dir = child->win32_res ? 0 : 1;
4650 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4652 memcpy (entries, &dir_entry, sizeof (dir_entry));
4653 entries += sizeof (dir_entry);
4660 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4665 MonoReflectionWin32Resource *win32_res;
4668 if (!assemblyb->win32_resources)
4672 * Resources are stored in a three level tree inside the PE file.
4673 * - level one contains a node for each type of resource
4674 * - level two contains a node for each resource
4675 * - level three contains a node for each instance of a resource for a
4676 * specific language.
4679 tree = resource_tree_create (assemblyb->win32_resources);
4681 /* Estimate the size of the encoded tree */
4683 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4684 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4685 size += mono_array_length (win32_res->res_data);
4687 /* Directory structure */
4688 size += mono_array_length (assemblyb->win32_resources) * 256;
4689 p = buf = g_malloc (size);
4691 resource_tree_encode (tree, p, p, &p);
4693 g_assert (p - buf < size);
4695 assembly->win32_res = g_malloc (p - buf);
4696 assembly->win32_res_size = p - buf;
4697 memcpy (assembly->win32_res, buf, p - buf);
4703 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4705 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4708 p += sizeof (MonoPEResourceDir);
4709 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4710 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4711 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4712 if (dir_entry->is_dir) {
4713 fixup_resource_directory (res_section, child, rva);
4715 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4716 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4719 p += sizeof (MonoPEResourceDirEntry);
4724 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4727 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4728 g_error ("WriteFile returned %d\n", GetLastError ());
4732 * mono_image_create_pefile:
4733 * @mb: a module builder object
4735 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4736 * assembly->pefile where it can be easily retrieved later in chunks.
4739 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4740 MonoMSDOSHeader *msdos;
4741 MonoDotNetHeader *header;
4742 MonoSectionTable *section;
4743 MonoCLIHeader *cli_header;
4744 guint32 size, image_size, virtual_base, text_offset;
4745 guint32 header_start, section_start, file_offset, virtual_offset;
4746 MonoDynamicImage *assembly;
4747 MonoReflectionAssemblyBuilder *assemblyb;
4748 MonoDynamicStream pefile_stream = {0};
4749 MonoDynamicStream *pefile = &pefile_stream;
4751 guint32 *rva, value;
4753 static const unsigned char msheader[] = {
4754 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4755 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4756 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4757 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4758 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4759 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4760 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4761 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4764 assemblyb = mb->assemblyb;
4766 mono_image_basic_init (assemblyb);
4767 assembly = mb->dynamic_image;
4769 assembly->pe_kind = assemblyb->pe_kind;
4770 assembly->machine = assemblyb->machine;
4771 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4772 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4774 mono_image_build_metadata (mb);
4776 if (mb->is_main && assemblyb->resources) {
4777 int len = mono_array_length (assemblyb->resources);
4778 for (i = 0; i < len; ++i)
4779 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4782 if (mb->resources) {
4783 int len = mono_array_length (mb->resources);
4784 for (i = 0; i < len; ++i)
4785 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4788 build_compressed_metadata (assembly);
4791 assembly_add_win32_resources (assembly, assemblyb);
4793 nsections = calc_section_size (assembly);
4795 /* The DOS header and stub */
4796 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4797 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4799 /* the dotnet header */
4800 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4802 /* the section tables */
4803 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4805 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4806 virtual_offset = VIRT_ALIGN;
4809 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4810 if (!assembly->sections [i].size)
4813 file_offset += FILE_ALIGN - 1;
4814 file_offset &= ~(FILE_ALIGN - 1);
4815 virtual_offset += VIRT_ALIGN - 1;
4816 virtual_offset &= ~(VIRT_ALIGN - 1);
4818 assembly->sections [i].offset = file_offset;
4819 assembly->sections [i].rva = virtual_offset;
4821 file_offset += assembly->sections [i].size;
4822 virtual_offset += assembly->sections [i].size;
4823 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4826 file_offset += FILE_ALIGN - 1;
4827 file_offset &= ~(FILE_ALIGN - 1);
4829 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4831 /* back-patch info */
4832 msdos = (MonoMSDOSHeader*)pefile->data;
4833 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4835 header = (MonoDotNetHeader*)(pefile->data + header_start);
4836 header->pesig [0] = 'P';
4837 header->pesig [1] = 'E';
4839 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4840 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4841 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4842 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4843 if (assemblyb->pekind == 1) {
4845 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4848 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4851 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4853 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4854 header->pe.pe_major = 6;
4855 header->pe.pe_minor = 0;
4856 size = assembly->sections [MONO_SECTION_TEXT].size;
4857 size += FILE_ALIGN - 1;
4858 size &= ~(FILE_ALIGN - 1);
4859 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4860 size = assembly->sections [MONO_SECTION_RSRC].size;
4861 size += FILE_ALIGN - 1;
4862 size &= ~(FILE_ALIGN - 1);
4863 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4864 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4865 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4866 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4867 /* pe_rva_entry_point always at the beginning of the text section */
4868 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4870 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4871 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4872 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4873 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4874 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4875 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4876 size = section_start;
4877 size += FILE_ALIGN - 1;
4878 size &= ~(FILE_ALIGN - 1);
4879 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4881 size += VIRT_ALIGN - 1;
4882 size &= ~(VIRT_ALIGN - 1);
4883 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4886 // Translate the PEFileKind value to the value expected by the Windows loader
4892 // PEFileKinds.Dll == 1
4893 // PEFileKinds.ConsoleApplication == 2
4894 // PEFileKinds.WindowApplication == 3
4897 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4898 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4900 if (assemblyb->pekind == 3)
4905 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4907 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4908 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4909 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4910 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4911 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4912 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4914 /* fill data directory entries */
4916 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4917 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4919 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4920 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4922 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4923 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4924 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4925 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4926 /* patch entrypoint name */
4927 if (assemblyb->pekind == 1)
4928 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4930 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4931 /* patch imported function RVA name */
4932 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4933 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4935 /* the import table */
4936 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4937 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4938 /* patch imported dll RVA name and other entries in the dir */
4939 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4940 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4941 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4942 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4943 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4944 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4946 p = (assembly->code.data + assembly->ilt_offset);
4947 value = (assembly->text_rva + assembly->imp_names_offset);
4948 *p++ = (value) & 0xff;
4949 *p++ = (value >> 8) & (0xff);
4950 *p++ = (value >> 16) & (0xff);
4951 *p++ = (value >> 24) & (0xff);
4953 /* the CLI header info */
4954 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4955 cli_header->ch_size = GUINT32_FROM_LE (72);
4956 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4957 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4958 if (assemblyb->entry_point) {
4959 guint32 table_idx = 0;
4960 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4961 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4962 table_idx = methodb->table_idx;
4964 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4966 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4968 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4970 /* The embedded managed resources */
4971 text_offset = assembly->text_rva + assembly->code.index;
4972 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4973 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4974 text_offset += assembly->resources.index;
4975 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4976 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4977 text_offset += assembly->meta_size;
4978 if (assembly->strong_name_size) {
4979 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4980 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4981 text_offset += assembly->strong_name_size;
4984 /* write the section tables and section content */
4985 section = (MonoSectionTable*)(pefile->data + section_start);
4986 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4987 static const char *section_names [] = {
4988 ".text", ".rsrc", ".reloc"
4990 if (!assembly->sections [i].size)
4992 strcpy (section->st_name, section_names [i]);
4993 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4994 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4995 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4996 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4997 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4998 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4999 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5003 checked_write_file (file, pefile->data, pefile->index);
5005 mono_dynamic_stream_reset (pefile);
5007 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5008 if (!assembly->sections [i].size)
5011 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5012 g_error ("SetFilePointer returned %d\n", GetLastError ());
5015 case MONO_SECTION_TEXT:
5016 /* patch entry point */
5017 p = (assembly->code.data + 2);
5018 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5019 *p++ = (value) & 0xff;
5020 *p++ = (value >> 8) & 0xff;
5021 *p++ = (value >> 16) & 0xff;
5022 *p++ = (value >> 24) & 0xff;
5024 checked_write_file (file, assembly->code.data, assembly->code.index);
5025 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5026 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5027 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5030 g_free (assembly->image.raw_metadata);
5032 case MONO_SECTION_RELOC: {
5036 guint16 type_and_offset;
5040 g_assert (sizeof (reloc) == 12);
5042 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5043 reloc.block_size = GUINT32_FROM_LE (12);
5046 * the entrypoint is always at the start of the text section
5047 * 3 is IMAGE_REL_BASED_HIGHLOW
5048 * 2 is patch_size_rva - text_rva
5050 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5053 checked_write_file (file, &reloc, sizeof (reloc));
5057 case MONO_SECTION_RSRC:
5058 if (assembly->win32_res) {
5060 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5061 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5062 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5066 g_assert_not_reached ();
5070 /* check that the file is properly padded */
5071 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5072 g_error ("SetFilePointer returned %d\n", GetLastError ());
5073 if (! SetEndOfFile (file))
5074 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5076 mono_dynamic_stream_reset (&assembly->code);
5077 mono_dynamic_stream_reset (&assembly->us);
5078 mono_dynamic_stream_reset (&assembly->blob);
5079 mono_dynamic_stream_reset (&assembly->guid);
5080 mono_dynamic_stream_reset (&assembly->sheap);
5082 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5083 g_hash_table_destroy (assembly->blob_cache);
5084 assembly->blob_cache = NULL;
5087 MonoReflectionModule *
5088 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5092 MonoImageOpenStatus status;
5093 MonoDynamicAssembly *assembly;
5094 guint32 module_count;
5095 MonoImage **new_modules;
5097 name = mono_string_to_utf8 (fileName);
5099 image = mono_image_open (name, &status);
5102 if (status == MONO_IMAGE_ERROR_ERRNO)
5103 exc = mono_get_exception_file_not_found (fileName);
5105 exc = mono_get_exception_bad_image_format (name);
5107 mono_raise_exception (exc);
5112 assembly = ab->dynamic_assembly;
5113 image->assembly = (MonoAssembly*)assembly;
5115 module_count = image->assembly->image->module_count;
5116 new_modules = g_new0 (MonoImage *, module_count + 1);
5118 if (image->assembly->image->modules)
5119 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5120 new_modules [module_count] = image;
5121 mono_image_addref (image);
5123 g_free (image->assembly->image->modules);
5124 image->assembly->image->modules = new_modules;
5125 image->assembly->image->module_count ++;
5127 mono_assembly_load_references (image, &status);
5129 mono_image_close (image);
5130 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5133 return mono_module_get_object (mono_domain_get (), image);
5137 * We need to return always the same object for MethodInfo, FieldInfo etc..
5138 * but we need to consider the reflected type.
5139 * type uses a different hash, since it uses custom hash/equal functions.
5144 MonoClass *refclass;
5148 reflected_equal (gconstpointer a, gconstpointer b) {
5149 const ReflectedEntry *ea = a;
5150 const ReflectedEntry *eb = b;
5152 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5156 reflected_hash (gconstpointer a) {
5157 const ReflectedEntry *ea = a;
5158 return mono_aligned_addr_hash (ea->item);
5161 #define CHECK_OBJECT(t,p,k) \
5167 mono_domain_lock (domain); \
5168 if (!domain->refobject_hash) \
5169 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5170 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5171 mono_domain_unlock (domain); \
5174 mono_domain_unlock (domain); \
5178 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5180 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5182 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5185 #define CACHE_OBJECT(t,p,o,k) \
5188 ReflectedEntry pe; \
5190 pe.refclass = (k); \
5191 mono_domain_lock (domain); \
5192 if (!domain->refobject_hash) \
5193 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5194 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5196 ReflectedEntry *e = ALLOC_REFENTRY; \
5198 e->refclass = (k); \
5199 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5202 mono_domain_unlock (domain); \
5207 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5209 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5213 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5215 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5219 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5221 MonoDynamicImage *image = moduleb->dynamic_image;
5222 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5225 MonoImage **new_modules;
5228 * FIXME: we already created an image in mono_image_basic_init (), but
5229 * we don't know which module it belongs to, since that is only
5230 * determined at assembly save time.
5232 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5233 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5235 moduleb->module.image = &image->image;
5236 moduleb->dynamic_image = image;
5237 register_module (mono_object_domain (moduleb), moduleb, image);
5239 /* register the module with the assembly */
5240 ass = ab->dynamic_assembly->assembly.image;
5241 module_count = ass->module_count;
5242 new_modules = g_new0 (MonoImage *, module_count + 1);
5245 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5246 new_modules [module_count] = &image->image;
5247 mono_image_addref (&image->image);
5249 g_free (ass->modules);
5250 ass->modules = new_modules;
5251 ass->module_count ++;
5256 * mono_assembly_get_object:
5257 * @domain: an app domain
5258 * @assembly: an assembly
5260 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5262 MonoReflectionAssembly*
5263 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5265 static MonoClass *System_Reflection_Assembly;
5266 MonoReflectionAssembly *res;
5268 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5269 if (!System_Reflection_Assembly)
5270 System_Reflection_Assembly = mono_class_from_name (
5271 mono_defaults.corlib, "System.Reflection", "Assembly");
5272 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5273 res->assembly = assembly;
5275 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5280 MonoReflectionModule*
5281 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5283 static MonoClass *System_Reflection_Module;
5284 MonoReflectionModule *res;
5287 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5288 if (!System_Reflection_Module)
5289 System_Reflection_Module = mono_class_from_name (
5290 mono_defaults.corlib, "System.Reflection", "Module");
5291 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5294 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5296 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5297 basename = g_path_get_basename (image->name);
5298 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5299 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5303 if (image->assembly->image == image) {
5304 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5307 g_assert (image->assembly->image->modules);
5309 for (i = 0; i < image->assembly->image->module_count; i++) {
5310 if (image->assembly->image->modules [i] == image)
5311 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5313 g_assert (res->token);
5316 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5319 MonoReflectionModule*
5320 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5322 static MonoClass *System_Reflection_Module;
5323 MonoReflectionModule *res;
5324 MonoTableInfo *table;
5325 guint32 cols [MONO_FILE_SIZE];
5327 guint32 i, name_idx;
5330 if (!System_Reflection_Module)
5331 System_Reflection_Module = mono_class_from_name (
5332 mono_defaults.corlib, "System.Reflection", "Module");
5333 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5335 table = &image->tables [MONO_TABLE_FILE];
5336 g_assert (table_index < table->rows);
5337 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5340 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5341 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5343 /* Check whenever the row has a corresponding row in the moduleref table */
5344 table = &image->tables [MONO_TABLE_MODULEREF];
5345 for (i = 0; i < table->rows; ++i) {
5346 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5347 val = mono_metadata_string_heap (image, name_idx);
5348 if (strcmp (val, name) == 0)
5349 res->image = image->modules [i];
5352 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5353 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5354 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5355 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5356 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5362 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5364 if ((t1->type != t2->type) ||
5365 (t1->byref != t2->byref))
5369 case MONO_TYPE_VOID:
5370 case MONO_TYPE_BOOLEAN:
5371 case MONO_TYPE_CHAR:
5382 case MONO_TYPE_STRING:
5385 case MONO_TYPE_OBJECT:
5386 case MONO_TYPE_TYPEDBYREF:
5388 case MONO_TYPE_VALUETYPE:
5389 case MONO_TYPE_CLASS:
5390 case MONO_TYPE_SZARRAY:
5391 return t1->data.klass == t2->data.klass;
5393 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5394 case MONO_TYPE_ARRAY:
5395 if (t1->data.array->rank != t2->data.array->rank)
5397 return t1->data.array->eklass == t2->data.array->eklass;
5398 case MONO_TYPE_GENERICINST: {
5400 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5402 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5403 &t2->data.generic_class->container_class->byval_arg))
5405 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5406 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5412 case MONO_TYPE_MVAR:
5413 return t1->data.generic_param == t2->data.generic_param;
5415 g_error ("implement type compare for %0x!", t1->type);
5423 mymono_metadata_type_hash (MonoType *t1)
5429 hash |= t1->byref << 6; /* do not collide with t1->type values */
5431 case MONO_TYPE_VALUETYPE:
5432 case MONO_TYPE_CLASS:
5433 case MONO_TYPE_SZARRAY:
5434 /* check if the distribution is good enough */
5435 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5437 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5438 case MONO_TYPE_GENERICINST: {
5440 MonoGenericInst *inst = t1->data.generic_class->inst;
5441 hash += g_str_hash (t1->data.generic_class->container_class->name);
5443 for (i = 0; i < inst->type_argc; ++i) {
5444 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5453 static MonoReflectionGenericClass*
5454 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5456 static MonoClass *System_Reflection_MonoGenericClass;
5457 MonoReflectionGenericClass *res;
5458 MonoInflatedGenericClass *gclass;
5461 if (!System_Reflection_MonoGenericClass) {
5462 System_Reflection_MonoGenericClass = mono_class_from_name (
5463 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5464 g_assert (System_Reflection_MonoGenericClass);
5467 gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
5468 gklass = gclass->generic_class.container_class;
5469 g_assert (gklass->generic_container);
5471 mono_class_init (gclass->klass);
5473 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5475 res->type.type = geninst;
5476 if (gklass->wastypebuilder && gklass->reflection_info)
5477 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5479 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5485 verify_safe_for_managed_space (MonoType *type)
5487 switch (type->type) {
5489 case MONO_TYPE_ARRAY:
5490 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5492 return verify_safe_for_managed_space (type->data.type);
5493 case MONO_TYPE_SZARRAY:
5494 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5495 case MONO_TYPE_GENERICINST: {
5496 MonoGenericInst *inst = type->data.generic_class->inst;
5500 for (i = 0; i < inst->type_argc; ++i)
5501 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5507 case MONO_TYPE_MVAR:
5508 return type->data.generic_param->owner != NULL;
5514 * mono_type_get_object:
5515 * @domain: an app domain
5518 * Return an System.MonoType object representing the type @type.
5521 mono_type_get_object (MonoDomain *domain, MonoType *type)
5523 MonoReflectionType *res;
5524 MonoClass *klass = mono_class_from_mono_type (type);
5526 mono_domain_lock (domain);
5527 if (!domain->type_hash)
5528 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5529 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5530 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5531 mono_domain_unlock (domain);
5534 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5535 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5536 mono_g_hash_table_insert (domain->type_hash, type, res);
5537 mono_domain_unlock (domain);
5541 if (!verify_safe_for_managed_space (type)) {
5542 mono_domain_unlock (domain);
5543 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5546 if (klass->reflection_info && !klass->wastypebuilder) {
5547 /* g_assert_not_reached (); */
5548 /* should this be considered an error condition? */
5550 mono_domain_unlock (domain);
5551 return klass->reflection_info;
5554 mono_class_init (klass);
5556 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5558 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5561 mono_g_hash_table_insert (domain->type_hash, type, res);
5562 mono_domain_unlock (domain);
5567 * mono_method_get_object:
5568 * @domain: an app domain
5570 * @refclass: the reflected type (can be NULL)
5572 * Return an System.Reflection.MonoMethod object representing the method @method.
5574 MonoReflectionMethod*
5575 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5578 * We use the same C representation for methods and constructors, but the type
5579 * name in C# is different.
5583 MonoReflectionMethod *ret;
5585 if (method->is_inflated) {
5586 MonoReflectionGenericMethod *gret;
5588 method = mono_get_inflated_method (method);
5589 refclass = method->klass;
5590 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5591 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5592 cname = "MonoGenericCMethod";
5594 cname = "MonoGenericMethod";
5595 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5597 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5598 gret->method.method = method;
5599 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5600 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5601 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5605 refclass = method->klass;
5607 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5608 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5609 cname = "MonoCMethod";
5611 cname = "MonoMethod";
5612 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5614 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5615 ret->method = method;
5616 MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name));
5617 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5618 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5622 * mono_field_get_object:
5623 * @domain: an app domain
5627 * Return an System.Reflection.MonoField object representing the field @field
5630 MonoReflectionField*
5631 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5633 MonoReflectionField *res;
5636 CHECK_OBJECT (MonoReflectionField *, field, klass);
5637 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5638 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5641 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5642 if (field->generic_info)
5643 res->attrs = field->generic_info->generic_type->attrs;
5645 res->attrs = field->type->attrs;
5646 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5647 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5651 * mono_property_get_object:
5652 * @domain: an app domain
5654 * @property: a property
5656 * Return an System.Reflection.MonoProperty object representing the property @property
5659 MonoReflectionProperty*
5660 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5662 MonoReflectionProperty *res;
5665 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5666 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5667 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5669 res->property = property;
5670 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5674 * mono_event_get_object:
5675 * @domain: an app domain
5679 * Return an System.Reflection.MonoEvent object representing the event @event
5682 MonoReflectionEvent*
5683 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5685 MonoReflectionEvent *res;
5688 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5689 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5690 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5693 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5697 * mono_param_get_objects:
5698 * @domain: an app domain
5701 * Return an System.Reflection.ParameterInfo array object representing the parameters
5702 * in the method @method.
5705 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5707 static MonoClass *System_Reflection_ParameterInfo;
5708 MonoArray *res = NULL;
5709 MonoReflectionMethod *member = NULL;
5710 MonoReflectionParameter *param = NULL;
5711 char **names, **blobs = NULL;
5712 guint32 *types = NULL;
5713 MonoType *type = NULL;
5714 MonoObject *dbnull = mono_get_dbnull_object (domain);
5715 MonoMarshalSpec **mspecs;
5718 if (!System_Reflection_ParameterInfo)
5719 System_Reflection_ParameterInfo = mono_class_from_name (
5720 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5722 if (!mono_method_signature (method)->param_count)
5723 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5725 /* Note: the cache is based on the address of the signature into the method
5726 * since we already cache MethodInfos with the method as keys.
5728 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5730 member = mono_method_get_object (domain, method, NULL);
5731 names = g_new (char *, mono_method_signature (method)->param_count);
5732 mono_method_get_param_names (method, (const char **) names);
5734 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
5735 mono_method_get_marshal_info (method, mspecs);
5737 res = mono_array_new (domain, System_Reflection_ParameterInfo, mono_method_signature (method)->param_count);
5738 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
5739 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5740 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, mono_method_signature (method)->params [i]));
5741 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5742 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5743 param->PositionImpl = i;
5744 param->AttrsImpl = mono_method_signature (method)->params [i]->attrs;
5746 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5747 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5751 blobs = g_new0 (char *, mono_method_signature (method)->param_count);
5752 types = g_new0 (guint32, mono_method_signature (method)->param_count);
5753 get_default_param_value_blobs (method, blobs, types);
5756 /* Build MonoType for the type from the Constant Table */
5758 type = g_new0 (MonoType, 1);
5759 type->type = types [i];
5760 type->data.klass = NULL;
5761 if (types [i] == MONO_TYPE_CLASS)
5762 type->data.klass = mono_defaults.object_class;
5764 type->data.klass = mono_class_from_mono_type (type);
5766 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5768 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5769 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5770 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5775 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5777 mono_array_setref (res, i, param);
5784 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5786 mono_metadata_free_marshal_spec (mspecs [i]);
5789 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5793 * mono_method_body_get_object:
5794 * @domain: an app domain
5797 * Return an System.Reflection.MethodBody object representing the method @method.
5799 MonoReflectionMethodBody*
5800 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5802 static MonoClass *System_Reflection_MethodBody = NULL;
5803 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5804 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5805 MonoReflectionMethodBody *ret;
5806 MonoMethodNormal *mn;
5807 MonoMethodHeader *header;
5808 guint32 method_rva, local_var_sig_token;
5810 unsigned char format, flags;
5813 if (!System_Reflection_MethodBody)
5814 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5815 if (!System_Reflection_LocalVariableInfo)
5816 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5817 if (!System_Reflection_ExceptionHandlingClause)
5818 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5820 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5822 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5823 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5824 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5825 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5827 mn = (MonoMethodNormal *)method;
5828 header = mono_method_get_header (method);
5830 /* Obtain local vars signature token */
5831 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5832 ptr = mono_image_rva_map (method->klass->image, method_rva);
5833 flags = *(const unsigned char *) ptr;
5834 format = flags & METHOD_HEADER_FORMAT_MASK;
5836 case METHOD_HEADER_TINY_FORMAT:
5837 case METHOD_HEADER_TINY_FORMAT1:
5838 local_var_sig_token = 0;
5840 case METHOD_HEADER_FAT_FORMAT:
5844 local_var_sig_token = read32 (ptr);
5847 g_assert_not_reached ();
5850 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5852 ret->init_locals = header->init_locals;
5853 ret->max_stack = header->max_stack;
5854 ret->local_var_sig_token = local_var_sig_token;
5855 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5856 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5859 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5860 for (i = 0; i < header->num_locals; ++i) {
5861 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5862 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5863 info->is_pinned = header->locals [i]->pinned;
5864 info->local_index = i;
5865 mono_array_setref (ret->locals, i, info);
5869 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5870 for (i = 0; i < header->num_clauses; ++i) {
5871 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5872 MonoExceptionClause *clause = &header->clauses [i];
5874 info->flags = clause->flags;
5875 info->try_offset = clause->try_offset;
5876 info->try_length = clause->try_len;
5877 info->handler_offset = clause->handler_offset;
5878 info->handler_length = clause->handler_len;
5879 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5880 info->filter_offset = clause->data.filter_offset;
5881 else if (clause->data.catch_class)
5882 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5884 mono_array_setref (ret->clauses, i, info);
5887 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5892 mono_get_dbnull_object (MonoDomain *domain)
5896 static MonoClassField *dbnull_value_field = NULL;
5898 if (!dbnull_value_field) {
5899 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5900 mono_class_init (klass);
5901 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5902 g_assert (dbnull_value_field);
5904 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5911 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5913 guint32 param_index, i, lastp, crow = 0;
5914 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5917 MonoClass *klass = method->klass;
5918 MonoImage *image = klass->image;
5919 MonoMethodSignature *methodsig = mono_method_signature (method);
5921 MonoTableInfo *constt;
5922 MonoTableInfo *methodt;
5923 MonoTableInfo *paramt;
5925 if (!methodsig->param_count)
5928 mono_class_init (klass);
5930 if (klass->image->dynamic) {
5931 MonoReflectionMethodAux *aux;
5932 if (method->is_inflated)
5933 method = ((MonoMethodInflated*)method)->declaring;
5934 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5935 if (aux && aux->param_defaults) {
5936 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5937 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5942 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5943 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5944 constt = &image->tables [MONO_TABLE_CONSTANT];
5946 idx = mono_method_get_index (method) - 1;
5947 g_assert (idx != -1);
5949 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5950 if (idx + 1 < methodt->rows)
5951 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5953 lastp = paramt->rows + 1;
5955 for (i = param_index; i < lastp; ++i) {
5958 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5959 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5961 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5964 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5969 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5970 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5971 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5978 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5983 MonoType *basetype = type;
5988 klass = mono_class_from_mono_type (type);
5989 if (klass->valuetype) {
5990 object = mono_object_new (domain, klass);
5991 retval = ((gchar *) object + sizeof (MonoObject));
5992 if (klass->enumtype)
5993 basetype = klass->enum_basetype;
5998 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6005 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6009 memset (assembly, 0, sizeof (MonoAssemblyName));
6011 assembly->culture = "";
6012 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6014 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6017 while (g_ascii_isspace (*p) || *p == ',') {
6026 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6028 assembly->major = strtoul (p, &s, 10);
6029 if (s == p || *s != '.')
6032 assembly->minor = strtoul (p, &s, 10);
6033 if (s == p || *s != '.')
6036 assembly->build = strtoul (p, &s, 10);
6037 if (s == p || *s != '.')
6040 assembly->revision = strtoul (p, &s, 10);
6044 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6046 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6047 assembly->culture = "";
6050 assembly->culture = p;
6051 while (*p && *p != ',') {
6055 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6057 if (strncmp (p, "null", 4) == 0) {
6062 while (*p && *p != ',') {
6065 len = (p - start + 1);
6066 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6067 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6068 g_strlcpy (assembly->public_key_token, start, len);
6071 while (*p && *p != ',')
6075 while (g_ascii_isspace (*p) || *p == ',') {
6089 * mono_reflection_parse_type:
6092 * Parse a type name as accepted by the GetType () method and output the info
6093 * extracted in the info structure.
6094 * the name param will be mangled, so, make a copy before passing it to this function.
6095 * The fields in info will be valid until the memory pointed to by name is valid.
6097 * See also mono_type_get_name () below.
6099 * Returns: 0 on parse error.
6102 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6103 MonoTypeNameParse *info)
6105 char *start, *p, *w, *temp, *last_point, *startn;
6106 int in_modifiers = 0;
6107 int isbyref = 0, rank, arity = 0, i;
6109 start = p = w = name;
6111 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6112 info->name = info->name_space = NULL;
6113 info->nested = NULL;
6114 info->modifiers = NULL;
6115 info->type_arguments = NULL;
6117 /* last_point separates the namespace from the name */
6123 *p = 0; /* NULL terminate the name */
6125 info->nested = g_list_append (info->nested, startn);
6126 /* we have parsed the nesting namespace + name */
6130 info->name_space = start;
6132 info->name = last_point + 1;
6134 info->name_space = (char *)"";
6153 i = strtol (p, &temp, 10);
6170 info->name_space = start;
6172 info->name = last_point + 1;
6174 info->name_space = (char *)"";
6181 if (isbyref) /* only one level allowed by the spec */
6184 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6188 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6194 info->type_arguments = g_ptr_array_new ();
6195 for (i = 0; i < arity; i++) {
6196 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6197 gboolean fqname = FALSE;
6199 g_ptr_array_add (info->type_arguments, subinfo);
6206 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6217 while (*p && (*p != ']'))
6225 if (g_ascii_isspace (*aname)) {
6232 !assembly_name_to_aname (&subinfo->assembly, aname))
6236 if (i + 1 < arity) {
6256 else if (*p != '*') /* '*' means unknown lower bound */
6262 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6273 if (g_ascii_isspace (*p)) {
6280 return 0; /* missing assembly name */
6281 if (!assembly_name_to_aname (&info->assembly, p))
6287 if (info->assembly.name)
6290 // *w = 0; /* terminate class name */
6292 if (!info->name || !*info->name)
6296 /* add other consistency checks */
6301 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6303 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6307 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6309 gboolean type_resolve = FALSE;
6312 if (info->assembly.name) {
6313 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6315 /* then we must load the assembly ourselve - see #60439 */
6316 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6320 image = assembly->image;
6321 } else if (!image) {
6322 image = mono_defaults.corlib;
6325 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6326 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6327 image = mono_defaults.corlib;
6328 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6335 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6342 image = mono_defaults.corlib;
6345 klass = mono_class_from_name_case (image, info->name_space, info->name);
6347 klass = mono_class_from_name (image, info->name_space, info->name);
6350 for (mod = info->nested; mod; mod = mod->next) {
6353 mono_class_init (klass);
6354 nested = klass->nested_classes;
6357 klass = nested->data;
6359 if (g_strcasecmp (klass->name, mod->data) == 0)
6362 if (strcmp (klass->name, mod->data) == 0)
6366 nested = nested->next;
6373 mono_class_init (klass);
6375 if (info->type_arguments) {
6376 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6377 MonoReflectionType *the_type;
6381 for (i = 0; i < info->type_arguments->len; i++) {
6382 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6384 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6385 if (!type_args [i]) {
6391 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6393 instance = mono_reflection_bind_generic_parameters (
6394 the_type, info->type_arguments->len, type_args);
6401 klass = mono_class_from_mono_type (instance);
6404 for (mod = info->modifiers; mod; mod = mod->next) {
6405 modval = GPOINTER_TO_UINT (mod->data);
6406 if (!modval) { /* byref: must be last modifier */
6407 return &klass->this_arg;
6408 } else if (modval == -1) {
6409 klass = mono_ptr_class_get (&klass->byval_arg);
6410 } else { /* array rank */
6411 klass = mono_array_class_get (klass, modval);
6413 mono_class_init (klass);
6416 return &klass->byval_arg;
6420 * mono_reflection_get_type:
6421 * @image: a metadata context
6422 * @info: type description structure
6423 * @ignorecase: flag for case-insensitive string compares
6424 * @type_resolve: whenever type resolve was already tried
6426 * Build a MonoType from the type description in @info.
6431 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6434 MonoReflectionAssembly *assembly;
6438 type = mono_reflection_get_type_internal (image, info, ignorecase);
6441 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6448 *type_resolve = TRUE;
6451 /* Reconstruct the type name */
6452 fullName = g_string_new ("");
6453 if (info->name_space && (info->name_space [0] != '\0'))
6454 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6456 g_string_printf (fullName, info->name);
6457 for (mod = info->nested; mod; mod = mod->next)
6458 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6460 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6462 if (assembly->assembly->dynamic) {
6463 /* Enumerate all modules */
6464 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6468 if (abuilder->modules) {
6469 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6470 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6471 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6477 if (!type && abuilder->loaded_modules) {
6478 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6479 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6480 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6487 type = mono_reflection_get_type_internal (assembly->assembly->image,
6490 g_string_free (fullName, TRUE);
6495 free_type_info (MonoTypeNameParse *info)
6497 g_list_free (info->modifiers);
6498 g_list_free (info->nested);
6500 if (info->type_arguments) {
6503 for (i = 0; i < info->type_arguments->len; i++) {
6504 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6506 free_type_info (subinfo);
6509 g_ptr_array_free (info->type_arguments, TRUE);
6514 * mono_reflection_type_from_name:
6516 * @image: a metadata context (can be NULL).
6518 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6519 * it defaults to get the type from @image or, if @image is NULL or loading
6520 * from it fails, uses corlib.
6524 mono_reflection_type_from_name (char *name, MonoImage *image)
6526 MonoType *type = NULL;
6527 MonoTypeNameParse info;
6530 /* Make a copy since parse_type modifies its argument */
6531 tmp = g_strdup (name);
6533 /*g_print ("requested type %s\n", str);*/
6534 if (mono_reflection_parse_type (tmp, &info)) {
6535 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6539 free_type_info (&info);
6544 * mono_reflection_get_token:
6546 * Return the metadata token of OBJ which should be an object
6547 * representing a metadata element.
6550 mono_reflection_get_token (MonoObject *obj)
6555 klass = obj->vtable->klass;
6557 if (strcmp (klass->name, "MethodBuilder") == 0) {
6558 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6560 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6561 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6562 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6564 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6565 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6566 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6567 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6568 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6569 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6570 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6571 } else if (strcmp (klass->name, "MonoType") == 0) {
6572 MonoReflectionType *tb = (MonoReflectionType *)obj;
6573 token = mono_class_from_mono_type (tb->type)->type_token;
6574 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6575 strcmp (klass->name, "MonoMethod") == 0 ||
6576 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6577 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6578 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6579 if (m->method->is_inflated) {
6580 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6581 return inflated->declaring->token;
6583 token = m->method->token;
6585 } else if (strcmp (klass->name, "MonoField") == 0) {
6586 MonoReflectionField *f = (MonoReflectionField*)obj;
6588 if (f->field->generic_info && f->field->generic_info->reflection_info)
6589 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6591 token = mono_class_get_field_token (f->field);
6592 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6593 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6595 token = mono_class_get_property_token (p->property);
6596 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6597 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6599 token = mono_class_get_event_token (p->event);
6600 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6601 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6603 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6604 } else if (strcmp (klass->name, "Module") == 0) {
6605 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6608 } else if (strcmp (klass->name, "Assembly") == 0) {
6609 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6611 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6612 MonoException *ex = mono_get_exception_not_implemented (msg);
6614 mono_raise_exception (ex);
6621 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6623 int slen, type = t->type;
6624 MonoClass *tklass = t->data.klass;
6630 case MONO_TYPE_BOOLEAN: {
6631 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6636 case MONO_TYPE_CHAR:
6638 case MONO_TYPE_I2: {
6639 guint16 *val = g_malloc (sizeof (guint16));
6644 #if SIZEOF_VOID_P == 4
6650 case MONO_TYPE_I4: {
6651 guint32 *val = g_malloc (sizeof (guint32));
6656 #if SIZEOF_VOID_P == 8
6657 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6662 case MONO_TYPE_I8: {
6663 guint64 *val = g_malloc (sizeof (guint64));
6668 case MONO_TYPE_VALUETYPE:
6669 if (t->data.klass->enumtype) {
6670 type = t->data.klass->enum_basetype->type;
6673 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6676 case MONO_TYPE_STRING:
6677 if (*p == (char)0xFF) {
6681 slen = mono_metadata_decode_value (p, &p);
6683 return mono_string_new_len (mono_domain_get (), p, slen);
6684 case MONO_TYPE_CLASS: {
6687 if (*p == (char)0xFF) {
6692 slen = mono_metadata_decode_value (p, &p);
6693 n = g_memdup (p, slen + 1);
6695 t = mono_reflection_type_from_name (n, image);
6697 g_warning ("Cannot load type '%s'", n);
6701 return mono_type_get_object (mono_domain_get (), t);
6705 case MONO_TYPE_OBJECT: {
6708 MonoClass *subc = NULL;
6713 } else if (subt == 0x0E) {
6714 type = MONO_TYPE_STRING;
6716 } else if (subt == 0x1D) {
6717 MonoType simple_type = {{0}};
6721 type = MONO_TYPE_SZARRAY;
6722 simple_type.type = etype;
6723 tklass = mono_class_from_mono_type (&simple_type);
6725 } else if (subt == 0x55) {
6728 slen = mono_metadata_decode_value (p, &p);
6729 n = g_memdup (p, slen + 1);
6731 t = mono_reflection_type_from_name (n, image);
6733 g_warning ("Cannot load type '%s'", n);
6736 subc = mono_class_from_mono_type (t);
6737 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6738 MonoType simple_type = {{0}};
6739 simple_type.type = subt;
6740 subc = mono_class_from_mono_type (&simple_type);
6742 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6744 val = load_cattr_value (image, &subc->byval_arg, p, end);
6745 obj = mono_object_new (mono_domain_get (), subc);
6746 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6750 case MONO_TYPE_SZARRAY: {
6752 guint32 i, alen, basetype;
6755 if (alen == 0xffffffff) {
6759 arr = mono_array_new (mono_domain_get(), tklass, alen);
6760 basetype = tklass->byval_arg.type;
6765 case MONO_TYPE_BOOLEAN:
6766 for (i = 0; i < alen; i++) {
6767 MonoBoolean val = *p++;
6768 mono_array_set (arr, MonoBoolean, i, val);
6771 case MONO_TYPE_CHAR:
6774 for (i = 0; i < alen; i++) {
6775 guint16 val = read16 (p);
6776 mono_array_set (arr, guint16, i, val);
6783 for (i = 0; i < alen; i++) {
6784 guint32 val = read32 (p);
6785 mono_array_set (arr, guint32, i, val);
6792 for (i = 0; i < alen; i++) {
6793 guint64 val = read64 (p);
6794 mono_array_set (arr, guint64, i, val);
6798 case MONO_TYPE_CLASS:
6799 case MONO_TYPE_OBJECT:
6800 case MONO_TYPE_STRING:
6801 for (i = 0; i < alen; i++) {
6802 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6803 mono_array_setref (arr, i, item);
6807 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6813 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6819 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6821 static MonoClass *klass;
6822 static MonoMethod *ctor;
6824 void *params [2], *unboxed;
6827 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6829 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6831 params [0] = mono_type_get_object (mono_domain_get (), t);
6833 retval = mono_object_new (mono_domain_get (), klass);
6834 unboxed = mono_object_unbox (retval);
6835 mono_runtime_invoke (ctor, unboxed, params, NULL);
6841 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6843 static MonoClass *klass;
6844 static MonoMethod *ctor;
6846 void *unboxed, *params [2];
6849 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6851 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6854 params [1] = typedarg;
6855 retval = mono_object_new (mono_domain_get (), klass);
6856 unboxed = mono_object_unbox (retval);
6857 mono_runtime_invoke (ctor, unboxed, params, NULL);
6863 type_is_reference (MonoType *type)
6865 switch (type->type) {
6866 case MONO_TYPE_BOOLEAN:
6867 case MONO_TYPE_CHAR:
6880 case MONO_TYPE_VALUETYPE:
6888 free_param_data (MonoMethodSignature *sig, void **params) {
6890 for (i = 0; i < sig->param_count; ++i) {
6891 if (!type_is_reference (sig->params [i]))
6892 g_free (params [i]);
6897 * Find the field index in the metadata FieldDef table.
6900 find_field_index (MonoClass *klass, MonoClassField *field) {
6903 for (i = 0; i < klass->field.count; ++i) {
6904 if (field == &klass->fields [i])
6905 return klass->field.first + 1 + i;
6911 * Find the property index in the metadata Property table.
6914 find_property_index (MonoClass *klass, MonoProperty *property) {
6917 for (i = 0; i < klass->property.count; ++i) {
6918 if (property == &klass->properties [i])
6919 return klass->property.first + 1 + i;
6925 * Find the event index in the metadata Event table.
6928 find_event_index (MonoClass *klass, MonoEvent *event) {
6931 for (i = 0; i < klass->event.count; ++i) {
6932 if (event == &klass->events [i])
6933 return klass->event.first + 1 + i;
6939 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
6941 const char *p = (const char*)data;
6943 guint32 i, j, num_named;
6947 mono_class_init (method->klass);
6950 attr = mono_object_new (mono_domain_get (), method->klass);
6951 mono_runtime_invoke (method, attr, NULL, NULL);
6955 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6958 /*g_print ("got attr %s\n", method->klass->name);*/
6960 /* Allocate using alloca so it gets GC tracking */
6961 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6965 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6966 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6970 attr = mono_object_new (mono_domain_get (), method->klass);
6971 mono_runtime_invoke (method, attr, params, NULL);
6972 free_param_data (method->signature, params);
6973 num_named = read16 (named);
6975 for (j = 0; j < num_named; j++) {
6977 gboolean is_boxed = FALSE;
6978 char *name, named_type, data_type;
6979 named_type = *named++;
6980 data_type = *named++; /* type of data */
6981 if (data_type == 0x51)
6984 if (data_type == 0x55) {
6987 type_len = mono_metadata_decode_blob_size (named, &named);
6988 type_name = g_malloc (type_len + 1);
6989 memcpy (type_name, named, type_len);
6990 type_name [type_len] = 0;
6992 /* FIXME: lookup the type and check type consistency */
6994 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6995 /* this seems to be the type of the element of the array */
6996 /* g_print ("skipping 0x%02x after prop\n", *named); */
6999 name_len = mono_metadata_decode_blob_size (named, &named);
7000 name = g_malloc (name_len + 1);
7001 memcpy (name, named, name_len);
7002 name [name_len] = 0;
7004 if (named_type == 0x53) {
7005 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7006 void *val = load_cattr_value (image, field->type, named, &named);
7007 mono_field_set_value (attr, field, val);
7008 if (!type_is_reference (field->type))
7010 } else if (named_type == 0x54) {
7013 MonoType *prop_type;
7015 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7016 /* can we have more that 1 arg in a custom attr named property? */
7017 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7018 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7019 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7020 mono_property_set_value (prop, attr, pparams, NULL);
7021 if (!type_is_reference (prop_type))
7022 g_free (pparams [0]);
7031 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7033 MonoArray *typedargs, *namedargs;
7034 MonoClass *attrklass;
7035 static MonoClass *klass;
7036 static MonoMethod *ctor;
7039 const char *p = (const char*)data;
7041 guint32 i, j, num_named;
7044 mono_class_init (method->klass);
7047 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7049 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
7051 domain = mono_domain_get ();
7053 /* This is for Attributes with no parameters */
7054 attr = mono_object_new (domain, klass);
7055 params [0] = mono_method_get_object (domain, method, NULL);
7056 params [1] = params [2] = NULL;
7057 mono_runtime_invoke (method, attr, params, NULL);
7061 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7064 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7068 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7069 MonoObject *obj, *typedarg;
7072 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7073 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7074 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7075 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7076 mono_array_setref (typedargs, i, typedarg);
7078 if (!type_is_reference (mono_method_signature (method)->params [i]))
7083 num_named = read16 (named);
7084 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7086 attrklass = method->klass;
7087 for (j = 0; j < num_named; j++) {
7089 char *name, named_type, data_type;
7090 named_type = *named++;
7091 data_type = *named++; /* type of data */
7092 if (data_type == 0x55) {
7095 type_len = mono_metadata_decode_blob_size (named, &named);
7096 type_name = g_malloc (type_len + 1);
7097 memcpy (type_name, named, type_len);
7098 type_name [type_len] = 0;
7100 /* FIXME: lookup the type and check type consistency */
7102 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
7103 /* this seems to be the type of the element of the array */
7104 /* g_print ("skipping 0x%02x after prop\n", *named); */
7107 name_len = mono_metadata_decode_blob_size (named, &named);
7108 name = g_malloc (name_len + 1);
7109 memcpy (name, named, name_len);
7110 name [name_len] = 0;
7112 if (named_type == 0x53) {
7113 MonoObject *obj, *typedarg, *namedarg;
7114 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7115 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7117 minfo = mono_field_get_object (domain, NULL, field);
7118 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7119 typedarg = create_cattr_typed_arg (field->type, obj);
7120 namedarg = create_cattr_named_arg (minfo, typedarg);
7121 mono_array_setref (namedargs, j, namedarg);
7122 if (!type_is_reference (field->type))
7124 } else if (named_type == 0x54) {
7125 MonoObject *obj, *typedarg, *namedarg;
7126 MonoType *prop_type;
7128 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7130 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7131 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7132 minfo = mono_property_get_object (domain, NULL, prop);
7133 val = load_cattr_value (image, prop_type, named, &named);
7134 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7135 typedarg = create_cattr_typed_arg (prop_type, obj);
7136 namedarg = create_cattr_named_arg (minfo, typedarg);
7137 mono_array_setref (namedargs, j, namedarg);
7138 if (!type_is_reference (prop_type))
7143 attr = mono_object_new (domain, klass);
7144 params [0] = mono_method_get_object (domain, method, NULL);
7145 params [1] = typedargs;
7146 params [2] = namedargs;
7147 mono_runtime_invoke (ctor, attr, params, NULL);
7152 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7159 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7160 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7161 for (i = 0; i < cinfo->num_attrs; ++i) {
7162 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7163 mono_array_setref (result, i, attr);
7169 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7177 for (i = 0; i < cinfo->num_attrs; ++i) {
7178 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7182 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7183 result = mono_array_new (mono_domain_get (), klass, n);
7185 for (i = 0; i < cinfo->num_attrs; ++i) {
7186 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7187 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7188 mono_array_setref (result, n, attr);
7196 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7199 static MonoClass *klass;
7204 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7206 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7207 for (i = 0; i < cinfo->num_attrs; ++i) {
7208 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7209 mono_array_setref (result, i, attr);
7215 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7217 guint32 mtoken, i, len;
7218 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7220 MonoCustomAttrInfo *ainfo;
7221 GList *tmp, *list = NULL;
7224 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7226 i = mono_metadata_custom_attrs_from_index (image, idx);
7230 while (i < ca->rows) {
7231 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7233 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7236 len = g_list_length (list);
7239 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7240 ainfo->num_attrs = len;
7241 ainfo->image = image;
7242 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7243 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7244 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7245 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7246 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7247 mtoken |= MONO_TOKEN_METHOD_DEF;
7249 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7250 mtoken |= MONO_TOKEN_MEMBER_REF;
7253 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7256 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7257 if (!ainfo->attrs [i].ctor)
7258 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7259 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7260 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7261 ainfo->attrs [i].data = (guchar*)data;
7269 mono_custom_attrs_from_method (MonoMethod *method)
7271 MonoCustomAttrInfo *cinfo;
7274 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7276 idx = mono_method_get_index (method);
7277 idx <<= MONO_CUSTOM_ATTR_BITS;
7278 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7279 return mono_custom_attrs_from_index (method->klass->image, idx);
7283 mono_custom_attrs_from_class (MonoClass *klass)
7285 MonoCustomAttrInfo *cinfo;
7288 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7290 idx = mono_metadata_token_index (klass->type_token);
7291 idx <<= MONO_CUSTOM_ATTR_BITS;
7292 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7293 return mono_custom_attrs_from_index (klass->image, idx);
7297 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7299 MonoCustomAttrInfo *cinfo;
7302 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7304 idx = 1; /* there is only one assembly */
7305 idx <<= MONO_CUSTOM_ATTR_BITS;
7306 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7307 return mono_custom_attrs_from_index (assembly->image, idx);
7310 static MonoCustomAttrInfo*
7311 mono_custom_attrs_from_module (MonoImage *image)
7313 MonoCustomAttrInfo *cinfo;
7316 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7318 idx = 1; /* there is only one module */
7319 idx <<= MONO_CUSTOM_ATTR_BITS;
7320 idx |= MONO_CUSTOM_ATTR_MODULE;
7321 return mono_custom_attrs_from_index (image, idx);
7325 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7327 MonoCustomAttrInfo *cinfo;
7330 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7332 idx = find_property_index (klass, property);
7333 idx <<= MONO_CUSTOM_ATTR_BITS;
7334 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7335 return mono_custom_attrs_from_index (klass->image, idx);
7339 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7341 MonoCustomAttrInfo *cinfo;
7344 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7346 idx = find_event_index (klass, event);
7347 idx <<= MONO_CUSTOM_ATTR_BITS;
7348 idx |= MONO_CUSTOM_ATTR_EVENT;
7349 return mono_custom_attrs_from_index (klass->image, idx);
7353 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7355 MonoCustomAttrInfo *cinfo;
7358 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7360 idx = find_field_index (klass, field);
7361 idx <<= MONO_CUSTOM_ATTR_BITS;
7362 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7363 return mono_custom_attrs_from_index (klass->image, idx);
7367 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7370 guint32 i, idx, method_index;
7371 guint32 param_list, param_last, param_pos, found;
7373 MonoReflectionMethodAux *aux;
7375 if (method->klass->image->dynamic) {
7376 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7377 if (!aux || !aux->param_cattr)
7379 return aux->param_cattr [param];
7382 image = method->klass->image;
7383 method_index = mono_method_get_index (method);
7384 ca = &image->tables [MONO_TABLE_METHOD];
7386 if (method->klass->generic_class || mono_method_signature (method)->generic_param_count) {
7387 /* FIXME FIXME FIXME */
7391 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7392 if (method_index == ca->rows) {
7393 ca = &image->tables [MONO_TABLE_PARAM];
7394 param_last = ca->rows + 1;
7396 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7397 ca = &image->tables [MONO_TABLE_PARAM];
7400 for (i = param_list; i < param_last; ++i) {
7401 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7402 if (param_pos == param) {
7410 idx <<= MONO_CUSTOM_ATTR_BITS;
7411 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7412 return mono_custom_attrs_from_index (image, idx);
7416 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7420 for (i = 0; i < ainfo->num_attrs; ++i) {
7421 klass = ainfo->attrs [i].ctor->klass;
7422 if (mono_class_has_parent (klass, attr_klass))
7429 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7436 for (i = 0; i < ainfo->num_attrs; ++i) {
7437 klass = ainfo->attrs [i].ctor->klass;
7438 if (mono_class_has_parent (klass, attr_klass)) {
7443 if (attr_index == -1)
7446 attrs = mono_custom_attrs_construct (ainfo);
7448 return mono_array_get (attrs, MonoObject*, attr_index);
7454 * mono_reflection_get_custom_attrs_info:
7455 * @obj: a reflection object handle
7457 * Return the custom attribute info for attributes defined for the
7458 * reflection handle @obj. The objects.
7461 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7464 MonoCustomAttrInfo *cinfo = NULL;
7466 klass = obj->vtable->klass;
7467 if (klass == mono_defaults.monotype_class) {
7468 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7469 klass = mono_class_from_mono_type (rtype->type);
7470 cinfo = mono_custom_attrs_from_class (klass);
7471 } else if (strcmp ("Assembly", klass->name) == 0) {
7472 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7473 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7474 } else if (strcmp ("Module", klass->name) == 0) {
7475 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7476 cinfo = mono_custom_attrs_from_module (module->image);
7477 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7478 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7479 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7480 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7481 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7482 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7483 } else if (strcmp ("MonoField", klass->name) == 0) {
7484 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7485 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7486 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7487 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7488 cinfo = mono_custom_attrs_from_method (rmethod->method);
7489 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7490 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7491 cinfo = mono_custom_attrs_from_method (method);
7492 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7493 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7494 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7495 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7496 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7497 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7498 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7499 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7500 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7501 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7502 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7503 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7504 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7505 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7506 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7507 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7508 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7509 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7510 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7511 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7512 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7513 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7514 } else { /* handle other types here... */
7515 g_error ("get custom attrs not yet supported for %s", klass->name);
7522 * mono_reflection_get_custom_attrs_by_type:
7523 * @obj: a reflection object handle
7525 * Return an array with all the custom attributes defined of the
7526 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7527 * of that type are returned. The objects are fully build.
7530 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7533 MonoCustomAttrInfo *cinfo;
7535 cinfo = mono_reflection_get_custom_attrs_info (obj);
7538 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7540 result = mono_custom_attrs_construct (cinfo);
7542 mono_custom_attrs_free (cinfo);
7545 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7546 result = mono_array_new (mono_domain_get (), klass, 0);
7553 * mono_reflection_get_custom_attrs:
7554 * @obj: a reflection object handle
7556 * Return an array with all the custom attributes defined of the
7557 * reflection handle @obj. The objects are fully build.
7560 mono_reflection_get_custom_attrs (MonoObject *obj)
7562 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7566 * mono_reflection_get_custom_attrs_data:
7567 * @obj: a reflection obj handle
7569 * Returns an array of System.Reflection.CustomAttributeData,
7570 * which include information about attributes reflected on
7571 * types loaded using the Reflection Only methods
7574 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7577 MonoCustomAttrInfo *cinfo;
7579 cinfo = mono_reflection_get_custom_attrs_info (obj);
7581 result = mono_custom_attrs_data_construct (cinfo);
7583 mono_custom_attrs_free (cinfo);
7586 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7587 result = mono_array_new (mono_domain_get (), klass, 0);
7594 * LOCKING: Assumes the loader lock is held.
7596 static MonoMethodSignature*
7597 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7598 MonoMethodSignature *sig;
7601 count = parameters? mono_array_length (parameters): 0;
7603 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7604 sig->param_count = count;
7605 sig->sentinelpos = -1; /* FIXME */
7606 for (i = 0; i < count; ++i) {
7607 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7608 sig->params [i] = pt->type;
7614 * LOCKING: Assumes the loader lock is held.
7616 static MonoMethodSignature*
7617 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7618 MonoMethodSignature *sig;
7620 sig = parameters_to_signature (mp, ctor->parameters);
7621 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7622 sig->ret = &mono_defaults.void_class->byval_arg;
7627 * LOCKING: Assumes the loader lock is held.
7629 static MonoMethodSignature*
7630 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7631 MonoMethodSignature *sig;
7633 sig = parameters_to_signature (mp, method->parameters);
7634 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7635 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7636 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7640 static MonoMethodSignature*
7641 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7642 MonoMethodSignature *sig;
7644 sig = parameters_to_signature (NULL, method->parameters);
7645 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7646 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7647 sig->generic_param_count = 0;
7652 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7654 MonoClass *klass = mono_object_class (prop);
7655 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7656 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7657 *name = mono_string_to_utf8 (pb->name);
7658 *type = pb->type->type;
7660 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7661 *name = g_strdup (p->property->name);
7662 if (p->property->get)
7663 *type = mono_method_signature (p->property->get)->ret;
7665 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7670 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7672 MonoClass *klass = mono_object_class (field);
7673 if (strcmp (klass->name, "FieldBuilder") == 0) {
7674 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7675 *name = mono_string_to_utf8 (fb->name);
7676 *type = fb->type->type;
7678 MonoReflectionField *f = (MonoReflectionField *)field;
7679 *name = g_strdup (f->field->name);
7680 *type = f->field->type;
7685 * Encode a value in a custom attribute stream of bytes.
7686 * The value to encode is either supplied as an object in argument val
7687 * (valuetypes are boxed), or as a pointer to the data in the
7689 * @type represents the type of the value
7690 * @buffer is the start of the buffer
7691 * @p the current position in the buffer
7692 * @buflen contains the size of the buffer and is used to return the new buffer size
7693 * if this needs to be realloced.
7694 * @retbuffer and @retp return the start and the position of the buffer
7697 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7699 MonoTypeEnum simple_type;
7701 if ((p-buffer) + 10 >= *buflen) {
7704 newbuf = g_realloc (buffer, *buflen);
7705 p = newbuf + (p-buffer);
7709 argval = ((char*)arg + sizeof (MonoObject));
7710 simple_type = type->type;
7712 switch (simple_type) {
7713 case MONO_TYPE_BOOLEAN:
7718 case MONO_TYPE_CHAR:
7721 swap_with_size (p, argval, 2, 1);
7727 swap_with_size (p, argval, 4, 1);
7733 swap_with_size (p, argval, 8, 1);
7736 case MONO_TYPE_VALUETYPE:
7737 if (type->data.klass->enumtype) {
7738 simple_type = type->data.klass->enum_basetype->type;
7741 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7744 case MONO_TYPE_STRING: {
7751 str = mono_string_to_utf8 ((MonoString*)arg);
7752 slen = strlen (str);
7753 if ((p-buffer) + 10 + slen >= *buflen) {
7757 newbuf = g_realloc (buffer, *buflen);
7758 p = newbuf + (p-buffer);
7761 mono_metadata_encode_value (slen, p, &p);
7762 memcpy (p, str, slen);
7767 case MONO_TYPE_CLASS: {
7775 k = mono_object_class (arg);
7776 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7777 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7778 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7780 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7781 slen = strlen (str);
7782 if ((p-buffer) + 10 + slen >= *buflen) {
7786 newbuf = g_realloc (buffer, *buflen);
7787 p = newbuf + (p-buffer);
7790 mono_metadata_encode_value (slen, p, &p);
7791 memcpy (p, str, slen);
7796 case MONO_TYPE_SZARRAY: {
7798 MonoClass *eclass, *arg_eclass;
7801 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7804 len = mono_array_length ((MonoArray*)arg);
7806 *p++ = (len >> 8) & 0xff;
7807 *p++ = (len >> 16) & 0xff;
7808 *p++ = (len >> 24) & 0xff;
7810 *retbuffer = buffer;
7811 eclass = type->data.klass;
7812 arg_eclass = mono_object_class (arg)->element_class;
7815 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7816 eclass = mono_defaults.object_class;
7818 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7819 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7820 int elsize = mono_class_array_element_size (arg_eclass);
7821 for (i = 0; i < len; ++i) {
7822 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7825 } else if (eclass->valuetype && arg_eclass->valuetype) {
7826 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7827 int elsize = mono_class_array_element_size (eclass);
7828 for (i = 0; i < len; ++i) {
7829 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7833 for (i = 0; i < len; ++i) {
7834 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7839 case MONO_TYPE_OBJECT: {
7845 * The parameter type is 'object' but the type of the actual
7846 * argument is not. So we have to add type information to the blob
7847 * too. This is completely undocumented in the spec.
7851 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7856 klass = mono_object_class (arg);
7858 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7861 } else if (klass->enumtype) {
7863 } else if (klass == mono_defaults.string_class) {
7864 simple_type = MONO_TYPE_STRING;
7867 } else if (klass->rank == 1) {
7868 simple_type = MONO_TYPE_SZARRAY;
7870 *p++ = klass->element_class->byval_arg.type;
7872 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7873 *p++ = simple_type = klass->byval_arg.type;
7876 g_error ("unhandled type in custom attr");
7878 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7879 slen = strlen (str);
7880 if ((p-buffer) + 10 + slen >= *buflen) {
7884 newbuf = g_realloc (buffer, *buflen);
7885 p = newbuf + (p-buffer);
7888 mono_metadata_encode_value (slen, p, &p);
7889 memcpy (p, str, slen);
7892 simple_type = klass->enum_basetype->type;
7896 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7899 *retbuffer = buffer;
7903 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7906 /* Preallocate a large enough buffer */
7907 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7908 char *str = type_get_qualified_name (type, NULL);
7914 len += strlen (name);
7916 if ((p-buffer) + 20 + len >= *buflen) {
7920 newbuf = g_realloc (buffer, *buflen);
7921 p = newbuf + (p-buffer);
7925 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7926 char *str = type_get_qualified_name (type, NULL);
7927 int slen = strlen (str);
7931 * This seems to be optional...
7934 mono_metadata_encode_value (slen, p, &p);
7935 memcpy (p, str, slen);
7938 } else if (type->type == MONO_TYPE_OBJECT) {
7940 } else if (type->type == MONO_TYPE_CLASS) {
7941 /* it should be a type: encode_cattr_value () has the check */
7944 mono_metadata_encode_value (type->type, p, &p);
7945 if (type->type == MONO_TYPE_SZARRAY)
7946 mono_metadata_encode_value (type->data.klass->this_arg.type, p, &p);
7948 len = strlen (name);
7949 mono_metadata_encode_value (len, p, &p);
7950 memcpy (p, name, len);
7952 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7954 *retbuffer = buffer;
7958 * mono_reflection_get_custom_attrs_blob:
7959 * @ctor: custom attribute constructor
7960 * @ctorArgs: arguments o the constructor
7966 * Creates the blob of data that needs to be saved in the metadata and that represents
7967 * the custom attributed described by @ctor, @ctorArgs etc.
7968 * Returns: a Byte array representing the blob of data.
7971 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7974 MonoMethodSignature *sig;
7979 MONO_ARCH_SAVE_REGS;
7981 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7982 /* sig is freed later so allocate it in the heap */
7983 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
7985 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7988 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7990 p = buffer = g_malloc (buflen);
7991 /* write the prolog */
7994 for (i = 0; i < sig->param_count; ++i) {
7995 arg = mono_array_get (ctorArgs, MonoObject*, i);
7996 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8000 i += mono_array_length (properties);
8002 i += mono_array_length (fields);
8004 *p++ = (i >> 8) & 0xff;
8007 for (i = 0; i < mono_array_length (properties); ++i) {
8011 prop = mono_array_get (properties, gpointer, i);
8012 get_prop_name_and_type (prop, &pname, &ptype);
8013 *p++ = 0x54; /* PROPERTY signature */
8014 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8021 for (i = 0; i < mono_array_length (fields); ++i) {
8025 field = mono_array_get (fields, gpointer, i);
8026 get_field_name_and_type (field, &fname, &ftype);
8027 *p++ = 0x53; /* FIELD signature */
8028 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8033 g_assert (p - buffer <= buflen);
8034 buflen = p - buffer;
8035 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8036 p = mono_array_addr (result, char, 0);
8037 memcpy (p, buffer, buflen);
8039 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8045 static void* reflection_info_desc = NULL;
8049 * mono_reflection_setup_internal_class:
8050 * @tb: a TypeBuilder object
8052 * Creates a MonoClass that represents the TypeBuilder.
8053 * This is a trick that lets us simplify a lot of reflection code
8054 * (and will allow us to support Build and Run assemblies easier).
8057 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8059 MonoClass *klass, *parent;
8061 MONO_ARCH_SAVE_REGS;
8063 mono_loader_lock ();
8066 /* check so we can compile corlib correctly */
8067 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8068 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8069 parent = tb->parent->type->data.klass;
8071 parent = my_mono_class_from_mono_type (tb->parent->type);
8077 /* the type has already being created: it means we just have to change the parent */
8078 if (tb->type.type) {
8079 klass = mono_class_from_mono_type (tb->type.type);
8080 klass->parent = NULL;
8081 /* fool mono_class_setup_parent */
8082 klass->supertypes = NULL;
8083 mono_class_setup_parent (klass, parent);
8084 mono_class_setup_mono_type (klass);
8085 mono_loader_unlock ();
8089 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8091 klass->image = &tb->module->dynamic_image->image;
8093 klass->inited = 1; /* we lie to the runtime */
8094 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8095 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8096 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8097 klass->flags = tb->attrs;
8099 klass->element_class = klass;
8102 if (!reflection_info_desc) {
8104 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);
8106 mono_gc_register_root (&klass->reflection_info, sizeof (gpointer), reflection_info_desc);
8108 klass->reflection_info = tb;
8110 /* Put into cache so mono_class_get () will find it */
8111 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8113 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8114 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8116 if (parent != NULL) {
8117 mono_class_setup_parent (klass, parent);
8118 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8119 const char *old_n = klass->name;
8120 /* trick to get relative numbering right when compiling corlib */
8121 klass->name = "BuildingObject";
8122 mono_class_setup_parent (klass, mono_defaults.object_class);
8123 klass->name = old_n;
8126 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8127 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8128 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8129 klass->instance_size = sizeof (MonoObject);
8130 klass->size_inited = 1;
8131 mono_class_setup_vtable_general (klass, NULL, 0);
8134 mono_class_setup_mono_type (klass);
8136 mono_class_setup_supertypes (klass);
8139 * FIXME: handle interfaces.
8142 tb->type.type = &klass->byval_arg;
8144 if (tb->nesting_type) {
8145 g_assert (tb->nesting_type->type);
8146 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8149 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8151 mono_loader_unlock ();
8155 * mono_reflection_setup_generic_class:
8156 * @tb: a TypeBuilder object
8158 * Setup the generic class before adding the first generic parameter.
8161 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8165 MONO_ARCH_SAVE_REGS;
8167 klass = my_mono_class_from_mono_type (tb->type.type);
8168 if (tb->generic_container)
8171 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8172 tb->generic_container->klass = klass;
8174 tb->generic_container->context.container = tb->generic_container;
8178 * mono_reflection_create_generic_class:
8179 * @tb: a TypeBuilder object
8181 * Creates the generic class after all generic parameters have been added.
8184 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8189 MONO_ARCH_SAVE_REGS;
8191 klass = my_mono_class_from_mono_type (tb->type.type);
8193 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8195 if (klass->generic_container || (count == 0))
8198 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
8200 klass->generic_container = tb->generic_container;
8202 klass->generic_container->type_argc = count;
8203 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8205 for (i = 0; i < count; i++) {
8206 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8207 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8208 g_assert (klass->generic_container->type_params [i].owner);
8211 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
8215 * mono_reflection_create_internal_class:
8216 * @tb: a TypeBuilder object
8218 * Actually create the MonoClass that is associated with the TypeBuilder.
8221 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8225 MONO_ARCH_SAVE_REGS;
8227 klass = my_mono_class_from_mono_type (tb->type.type);
8229 mono_loader_lock ();
8230 if (klass->enumtype && klass->enum_basetype == NULL) {
8231 MonoReflectionFieldBuilder *fb;
8234 g_assert (tb->fields != NULL);
8235 g_assert (mono_array_length (tb->fields) >= 1);
8237 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8239 klass->enum_basetype = fb->type->type;
8240 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8241 if (!klass->element_class)
8242 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8245 * get the element_class from the current corlib.
8247 ec = default_class_from_mono_type (klass->enum_basetype);
8248 klass->instance_size = ec->instance_size;
8249 klass->size_inited = 1;
8251 * this is almost safe to do with enums and it's needed to be able
8252 * to create objects of the enum type (for use in SetConstant).
8254 /* FIXME: Does this mean enums can't have method overrides ? */
8255 mono_class_setup_vtable_general (klass, NULL, 0);
8257 mono_loader_unlock ();
8260 static MonoMarshalSpec*
8261 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8262 MonoReflectionMarshal *minfo)
8264 MonoMarshalSpec *res;
8266 res = g_new0 (MonoMarshalSpec, 1);
8267 res->native = minfo->type;
8269 switch (minfo->type) {
8270 case MONO_NATIVE_LPARRAY:
8271 res->data.array_data.elem_type = minfo->eltype;
8272 if (minfo->has_size) {
8273 res->data.array_data.param_num = minfo->param_num;
8274 res->data.array_data.num_elem = minfo->count;
8275 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8278 res->data.array_data.param_num = -1;
8279 res->data.array_data.num_elem = -1;
8280 res->data.array_data.elem_mult = -1;
8284 case MONO_NATIVE_BYVALTSTR:
8285 case MONO_NATIVE_BYVALARRAY:
8286 res->data.array_data.num_elem = minfo->count;
8289 case MONO_NATIVE_CUSTOM:
8290 if (minfo->marshaltyperef)
8291 res->data.custom_data.custom_name =
8292 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8294 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8304 MonoReflectionMarshal*
8305 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8306 MonoMarshalSpec *spec)
8308 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8309 MonoReflectionMarshal *minfo;
8312 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8313 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8314 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8315 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8318 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8319 minfo->type = spec->native;
8321 switch (minfo->type) {
8322 case MONO_NATIVE_LPARRAY:
8323 minfo->eltype = spec->data.array_data.elem_type;
8324 minfo->count = spec->data.array_data.num_elem;
8325 minfo->param_num = spec->data.array_data.param_num;
8328 case MONO_NATIVE_BYVALTSTR:
8329 case MONO_NATIVE_BYVALARRAY:
8330 minfo->count = spec->data.array_data.num_elem;
8333 case MONO_NATIVE_CUSTOM:
8334 if (spec->data.custom_data.custom_name) {
8335 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8337 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8339 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8341 if (spec->data.custom_data.cookie)
8342 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8353 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8354 ReflectionMethodBuilder *rmb,
8355 MonoMethodSignature *sig)
8358 MonoMethodNormal *pm;
8359 MonoMarshalSpec **specs;
8360 MonoReflectionMethodAux *method_aux;
8365 g_assert (!klass->generic_class);
8368 * Methods created using a MethodBuilder should have their memory allocated
8369 * inside the image mempool, while dynamic methods should have their memory
8372 dynamic = rmb->refs != NULL;
8373 mp = dynamic ? NULL : klass->image->mempool;
8375 mono_loader_lock ();
8377 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8378 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8379 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8381 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8383 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8385 pm = (MonoMethodNormal*)m;
8388 m->flags = rmb->attrs;
8389 m->iflags = rmb->iattrs;
8390 m->name = dynamic ? mono_string_to_utf8 (rmb->name) : mono_string_to_utf8_mp (mp, rmb->name);
8394 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8396 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8397 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8400 m->signature->pinvoke = 1;
8401 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8402 m->signature->pinvoke = 1;
8404 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8406 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8407 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8409 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8411 if (klass->image->dynamic)
8412 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8414 mono_loader_unlock ();
8417 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8418 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8419 MonoMethodHeader *header;
8421 gint32 max_stack, i;
8422 gint32 num_locals = 0;
8423 gint32 num_clauses = 0;
8427 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8428 code_size = rmb->ilgen->code_len;
8429 max_stack = rmb->ilgen->max_stack;
8430 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8431 if (rmb->ilgen->ex_handlers)
8432 num_clauses = method_count_clauses (rmb->ilgen);
8435 code = mono_array_addr (rmb->code, guint8, 0);
8436 code_size = mono_array_length (rmb->code);
8437 /* we probably need to run a verifier on the code... */
8447 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8448 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8449 header->code_size = code_size;
8450 header->code = mp_g_malloc (mp, code_size);
8451 memcpy ((char*)header->code, code, code_size);
8452 header->max_stack = max_stack;
8453 header->init_locals = rmb->init_locals;
8454 header->num_locals = num_locals;
8456 for (i = 0; i < num_locals; ++i) {
8457 MonoReflectionLocalBuilder *lb =
8458 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8460 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8461 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8464 header->num_clauses = num_clauses;
8466 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8467 rmb->ilgen, num_clauses);
8470 pm->header = header;
8473 if (rmb->generic_params) {
8474 int count = mono_array_length (rmb->generic_params);
8475 MonoGenericContainer *container;
8476 MonoGenericContext *context;
8478 m->generic_container = container = rmb->generic_container;
8479 container->type_argc = count;
8480 container->type_params = g_new0 (MonoGenericParam, count);
8482 for (i = 0; i < count; i++) {
8483 MonoReflectionGenericParam *gp =
8484 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8486 container->type_params [i] = *gp->type.type->data.generic_param;
8487 container->type_params [i].method = m;
8490 context = &container->context;
8491 context->container = container;
8492 if (klass->generic_container) {
8493 container->parent = klass->generic_container;
8494 context->gclass = klass->generic_container->context.gclass;
8496 context->gmethod = mono_get_shared_generic_method (container);
8500 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8504 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8506 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8507 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8508 for (i = 0; i < rmb->nrefs; ++i)
8509 data [i + 1] = rmb->refs [i];
8514 /* Parameter info */
8517 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8518 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8519 for (i = 0; i <= m->signature->param_count; ++i) {
8520 MonoReflectionParamBuilder *pb;
8521 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8522 if ((i > 0) && (pb->attrs)) {
8523 /* Make a copy since it might point to a shared type structure */
8524 /* FIXME: Alloc this from a mempool */
8525 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)));
8526 m->signature->params [i - 1]->attrs = pb->attrs;
8529 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8530 MonoDynamicImage *assembly;
8531 guint32 idx, def_type, len;
8535 if (!method_aux->param_defaults) {
8536 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8537 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8539 assembly = (MonoDynamicImage*)klass->image;
8540 idx = encode_constant (assembly, pb->def_value, &def_type);
8541 /* Copy the data from the blob since it might get realloc-ed */
8542 p = assembly->blob.data + idx;
8543 len = mono_metadata_decode_blob_size (p, &p2);
8545 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8546 method_aux->param_default_types [i] = def_type;
8547 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8551 method_aux->param_names [i] = dynamic ? mono_string_to_utf8 (pb->name) : mono_string_to_utf8_mp (mp, pb->name);
8553 if (!method_aux->param_cattr)
8554 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8555 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8561 /* Parameter marshalling */
8564 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8565 MonoReflectionParamBuilder *pb;
8566 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8567 if (pb->marshal_info) {
8569 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8570 specs [pb->position] =
8571 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8575 if (specs != NULL) {
8577 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8578 method_aux->param_marshall = specs;
8581 if (klass->image->dynamic && method_aux)
8582 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8584 mono_loader_unlock ();
8590 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8592 ReflectionMethodBuilder rmb;
8593 MonoMethodSignature *sig;
8595 mono_loader_lock ();
8596 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8597 mono_loader_unlock ();
8599 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8601 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8602 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8604 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8605 /* ilgen is no longer needed */
8613 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8615 ReflectionMethodBuilder rmb;
8616 MonoMethodSignature *sig;
8618 mono_loader_lock ();
8619 sig = method_builder_to_signature (klass->image->mempool, mb);
8620 mono_loader_unlock ();
8622 reflection_methodbuilder_from_method_builder (&rmb, mb);
8624 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8625 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8627 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8628 /* ilgen is no longer needed */
8634 static MonoClassField*
8635 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8637 MonoClassField *field;
8641 field = g_new0 (MonoClassField, 1);
8643 field->name = mono_string_to_utf8 (fb->name);
8645 /* FIXME: handle type modifiers */
8646 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8647 field->type->attrs = fb->attrs;
8649 field->type = fb->type->type;
8651 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8652 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8653 if (fb->offset != -1)
8654 field->offset = fb->offset;
8655 field->parent = klass;
8656 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8658 if (fb->def_value) {
8659 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8660 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8661 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8662 /* Copy the data from the blob since it might get realloc-ed */
8663 p = assembly->blob.data + idx;
8664 len = mono_metadata_decode_blob_size (p, &p2);
8666 field->data = g_malloc (len);
8667 memcpy ((gpointer)field->data, p, len);
8674 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8677 MonoReflectionTypeBuilder *tb = NULL;
8678 MonoGenericClass *gclass, *cached;
8679 MonoInflatedGenericClass *igclass;
8680 MonoDynamicGenericClass *dgclass = NULL;
8681 gboolean is_dynamic = FALSE;
8686 klass = mono_class_from_mono_type (type->type);
8687 if (!klass->generic_container && !klass->generic_class &&
8688 !(klass->nested_in && klass->nested_in->generic_container))
8691 mono_loader_lock ();
8693 domain = mono_object_domain (type);
8695 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8696 tb = (MonoReflectionTypeBuilder *) type;
8699 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8700 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8701 MonoReflectionType *rgt = rgi->generic_type;
8703 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8704 tb = (MonoReflectionTypeBuilder *) rgt;
8707 } else if (klass->wastypebuilder) {
8708 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8714 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8715 igclass = &dgclass->generic_class;
8716 gclass = &igclass->generic_class;
8717 gclass->is_dynamic = TRUE;
8718 gclass->is_inflated = TRUE;
8720 igclass = g_new0 (MonoInflatedGenericClass, 1);
8721 gclass = &igclass->generic_class;
8722 gclass->is_inflated = TRUE;
8725 gclass->inst = g_new0 (MonoGenericInst, 1);
8727 gclass->inst->type_argc = type_argc;
8728 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8729 gclass->inst->is_reference = 1;
8731 for (i = 0; i < gclass->inst->type_argc; ++i) {
8732 MonoType *t = dup_type (types [i]);
8734 if (!gclass->inst->is_open)
8735 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8736 if (gclass->inst->is_reference)
8737 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8738 gclass->inst->type_argv [i] = t;
8741 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8743 gclass->container_class = klass;
8745 if (klass->generic_class) {
8746 MonoGenericClass *kgclass = klass->generic_class;
8747 MonoGenericClass *ogclass = gclass;
8749 ogclass->context = g_new0 (MonoGenericContext, 1);
8750 ogclass->context->container = gclass->container_class->generic_container;
8751 ogclass->context->gclass = gclass;
8754 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8755 igclass = &dgclass->generic_class;
8756 gclass = &igclass->generic_class;
8757 gclass->is_dynamic = TRUE;
8758 gclass->is_inflated = TRUE;
8760 igclass = g_new0 (MonoInflatedGenericClass, 1);
8761 gclass = &igclass->generic_class;
8762 gclass->is_inflated = TRUE;
8765 gclass->inst = g_new0 (MonoGenericInst, 1);
8767 gclass->inst->type_argc = kgclass->inst->type_argc;
8768 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8769 gclass->inst->is_reference = 1;
8771 for (i = 0; i < gclass->inst->type_argc; i++) {
8772 MonoType *t = kgclass->inst->type_argv [i];
8774 t = mono_class_inflate_generic_type (t, ogclass->context);
8776 if (!gclass->inst->is_open)
8777 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8778 if (gclass->inst->is_reference)
8779 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8781 gclass->inst->type_argv [i] = t;
8784 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8786 gclass->container_class = kgclass->container_class;
8789 geninst = g_new0 (MonoType, 1);
8790 geninst->type = MONO_TYPE_GENERICINST;
8792 cached = mono_metadata_lookup_generic_class (gclass);
8795 mono_loader_unlock ();
8796 geninst->data.generic_class = cached;
8800 geninst->data.generic_class = gclass;
8802 gclass->context = g_new0 (MonoGenericContext, 1);
8803 gclass->context->container = gclass->container_class->generic_container;
8804 gclass->context->gclass = gclass;
8806 mono_loader_unlock ();
8812 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8815 MonoGenericClass *gclass, *cached;
8816 MonoInflatedGenericClass *igclass;
8820 klass = mono_class_from_mono_type (type);
8821 if (!klass->generic_container && !klass->generic_class &&
8822 !(klass->nested_in && klass->nested_in->generic_container))
8825 mono_loader_lock ();
8827 igclass = g_new0 (MonoInflatedGenericClass, 1);
8828 gclass = &igclass->generic_class;
8829 gclass->is_inflated = TRUE;
8831 gclass->inst = g_new0 (MonoGenericInst, 1);
8832 gclass->inst->type_argc = type_argc;
8833 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8834 gclass->inst->is_reference = 1;
8836 for (i = 0; i < gclass->inst->type_argc; ++i) {
8837 MonoType *t = dup_type (types [i]);
8839 if (!gclass->inst->is_open)
8840 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8841 if (gclass->inst->is_reference)
8842 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8844 gclass->inst->type_argv [i] = t;
8847 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8849 gclass->container_class = klass;
8851 if (klass->generic_class) {
8852 MonoGenericClass *kgclass = klass->generic_class;
8853 MonoGenericClass *ogclass = gclass;
8855 gclass->context = g_new0 (MonoGenericContext, 1);
8856 gclass->context->container = gclass->container_class->generic_container;
8857 gclass->context->gclass = gclass;
8859 igclass = g_new0 (MonoInflatedGenericClass, 1);
8860 gclass = &igclass->generic_class;
8861 gclass->is_inflated = TRUE;
8863 gclass->inst = g_new0 (MonoGenericInst, 1);
8864 gclass->inst->type_argc = kgclass->inst->type_argc;
8865 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8866 gclass->inst->is_reference = 1;
8868 for (i = 0; i < gclass->inst->type_argc; i++) {
8869 MonoType *t = kgclass->inst->type_argv [i];
8871 t = mono_class_inflate_generic_type (t, ogclass->context);
8873 if (!gclass->inst->is_open)
8874 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8875 if (gclass->inst->is_reference)
8876 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8878 gclass->inst->type_argv [i] = t;
8881 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8883 gclass->container_class = kgclass->container_class;
8886 geninst = g_new0 (MonoType, 1);
8887 geninst->type = MONO_TYPE_GENERICINST;
8889 cached = mono_metadata_lookup_generic_class (gclass);
8892 mono_loader_unlock ();
8893 geninst->data.generic_class = cached;
8897 geninst->data.generic_class = gclass;
8899 gclass->context = g_new0 (MonoGenericContext, 1);
8900 gclass->context->container = gclass->container_class->generic_container;
8901 gclass->context->gclass = gclass;
8903 mono_loader_unlock ();
8908 static inline MonoType*
8909 dup_type (const MonoType *original)
8911 MonoType *r = g_new0 (MonoType, 1);
8913 r->attrs = original->attrs;
8914 r->byref = original->byref;
8915 if (original->type == MONO_TYPE_PTR)
8916 r->data.type = dup_type (original->data.type);
8917 else if (original->type == MONO_TYPE_ARRAY)
8918 r->data.array = mono_dup_array_type (original->data.array);
8919 else if (original->type == MONO_TYPE_FNPTR)
8920 r->data.method = mono_metadata_signature_deep_dup (original->data.method);
8921 mono_stats.generics_metadata_size += sizeof (MonoType);
8925 MonoReflectionMethod*
8926 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8928 MonoMethod *method, *inflated;
8929 MonoReflectionMethodBuilder *mb = NULL;
8930 MonoGenericContainer *container;
8931 MonoGenericMethod *gmethod;
8932 MonoGenericContext *context;
8933 MonoGenericInst *ginst;
8936 MONO_ARCH_SAVE_REGS;
8937 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8938 MonoReflectionTypeBuilder *tb;
8941 mb = (MonoReflectionMethodBuilder *) rmethod;
8942 tb = (MonoReflectionTypeBuilder *) mb->type;
8943 klass = mono_class_from_mono_type (tb->type.type);
8945 method = methodbuilder_to_mono_method (klass, mb);
8947 method = rmethod->method;
8950 method = mono_get_inflated_method (method);
8952 count = mono_method_signature (method)->generic_param_count;
8953 if (count != mono_array_length (types))
8956 container = method->generic_container;
8957 g_assert (container);
8959 if (!container->method_hash)
8960 container->method_hash = g_hash_table_new (
8961 (GHashFunc) mono_metadata_generic_method_hash,
8962 (GCompareFunc) mono_metadata_generic_method_equal);
8964 ginst = g_new0 (MonoGenericInst,1 );
8965 ginst->type_argc = count;
8966 ginst->type_argv = g_new0 (MonoType *, count);
8967 ginst->is_reference = 1;
8968 for (i = 0; i < count; i++) {
8969 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8970 ginst->type_argv [i] = dup_type (garg->type);
8972 if (!ginst->is_open)
8973 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8974 if (ginst->is_reference)
8975 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8977 ginst = mono_metadata_lookup_generic_inst (ginst);
8979 gmethod = g_new0 (MonoGenericMethod, 1);
8980 gmethod->generic_class = method->klass->generic_class;
8981 gmethod->container = container;
8982 gmethod->inst = ginst;
8984 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8988 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8991 gmethod->reflection_info = rmethod;
8993 context = g_new0 (MonoGenericContext, 1);
8994 context->container = container;
8995 context->gclass = method->klass->generic_class;
8996 context->gmethod = gmethod;
8998 if (method->is_inflated)
8999 method = ((MonoMethodInflated *) method)->declaring;
9001 inflated = mono_class_inflate_generic_method (method, context);
9002 g_hash_table_insert (container->method_hash, gmethod, inflated);
9004 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9008 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
9010 MonoGenericMethod *gmethod = NULL;
9011 MonoInflatedGenericClass *gclass;
9012 MonoGenericContext *context;
9016 klass = mono_class_from_mono_type (type->type.type);
9017 gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
9018 n = mono_method_signature (method)->generic_param_count;
9020 context = gclass->generic_class.context;
9021 g_assert (context && context->container);
9023 gmethod = g_new0 (MonoGenericMethod, 1);
9024 gmethod->generic_class = &gclass->generic_class;
9025 gmethod->container = method->generic_container;
9026 gmethod->reflection_info = obj;
9028 gmethod->inst = g_new0 (MonoGenericInst, 1);
9029 gmethod->inst->type_argc = n;
9030 gmethod->inst->type_argv = g_new0 (MonoType *, n);
9032 for (i = 0; i < n; i++) {
9033 MonoGenericParam *gparam = &method->generic_container->type_params [i];
9034 g_assert (gparam->pklass);
9035 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
9038 g_assert (gmethod->container->parent == context->container);
9040 context = g_new0 (MonoGenericContext, 1);
9041 context->container = gmethod->container;
9042 context->gclass = &gclass->generic_class;
9043 context->gmethod = gmethod;
9046 return mono_class_inflate_generic_method (method, context);
9050 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9055 gklass = mono_class_from_mono_type (type->generic_type->type);
9057 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9058 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9059 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9060 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9061 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9062 method = ((MonoReflectionMethod *) obj)->method;
9064 method = NULL; /* prevent compiler warning */
9065 g_assert_not_reached ();
9068 return inflate_mono_method (type, method, obj);
9072 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9073 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9076 MonoGenericClass *gclass;
9077 MonoDynamicGenericClass *dgclass;
9078 MonoClass *klass, *gklass;
9081 MONO_ARCH_SAVE_REGS;
9083 klass = mono_class_from_mono_type (type->type.type);
9084 gclass = type->type.type->data.generic_class;
9086 g_assert (gclass->is_dynamic);
9087 dgclass = (MonoDynamicGenericClass *) gclass;
9089 if (dgclass->initialized)
9092 gklass = gclass->container_class;
9093 mono_class_init (gklass);
9095 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9096 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9097 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9098 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9099 dgclass->count_events = events ? mono_array_length (events) : 0;
9101 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9102 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9103 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9104 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9105 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9107 for (i = 0; i < dgclass->count_methods; i++) {
9108 MonoObject *obj = mono_array_get (methods, gpointer, i);
9110 dgclass->methods [i] = inflate_method (type, obj);
9113 for (i = 0; i < dgclass->count_ctors; i++) {
9114 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9116 dgclass->ctors [i] = inflate_method (type, obj);
9119 for (i = 0; i < dgclass->count_fields; i++) {
9120 MonoObject *obj = mono_array_get (fields, gpointer, i);
9121 MonoClassField *field;
9122 MonoInflatedField *ifield;
9124 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9125 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9126 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9127 field = ((MonoReflectionField *) obj)->field;
9129 field = NULL; /* prevent compiler warning */
9130 g_assert_not_reached ();
9133 ifield = g_new0 (MonoInflatedField, 1);
9134 ifield->generic_type = field->type;
9135 ifield->reflection_info = obj;
9137 dgclass->fields [i] = *field;
9138 dgclass->fields [i].parent = klass;
9139 dgclass->fields [i].generic_info = ifield;
9140 dgclass->fields [i].type = mono_class_inflate_generic_type (
9141 field->type, dgclass->generic_class.generic_class.context);
9144 for (i = 0; i < dgclass->count_properties; i++) {
9145 MonoObject *obj = mono_array_get (properties, gpointer, i);
9146 MonoProperty *property = &dgclass->properties [i];
9148 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9149 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9151 property->parent = klass;
9152 property->attrs = pb->attrs;
9153 property->name = mono_string_to_utf8 (pb->name);
9155 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9157 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9158 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9159 *property = *((MonoReflectionProperty *) obj)->property;
9162 property->get = inflate_mono_method (type, property->get, NULL);
9164 property->set = inflate_mono_method (type, property->set, NULL);
9166 g_assert_not_reached ();
9169 for (i = 0; i < dgclass->count_events; i++) {
9170 MonoObject *obj = mono_array_get (events, gpointer, i);
9171 MonoEvent *event = &dgclass->events [i];
9173 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9174 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9176 event->parent = klass;
9177 event->attrs = eb->attrs;
9178 event->name = mono_string_to_utf8 (eb->name);
9180 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9181 if (eb->remove_method)
9182 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9183 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9184 *event = *((MonoReflectionEvent *) obj)->event;
9187 event->add = inflate_mono_method (type, event->add, NULL);
9189 event->remove = inflate_mono_method (type, event->remove, NULL);
9191 g_assert_not_reached ();
9194 dgclass->initialized = TRUE;
9198 ensure_runtime_vtable (MonoClass *klass)
9200 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9203 if (!tb || klass->wastypebuilder)
9206 ensure_runtime_vtable (klass->parent);
9208 num = tb->ctors? mono_array_length (tb->ctors): 0;
9209 num += tb->num_methods;
9210 klass->method.count = num;
9211 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9212 num = tb->ctors? mono_array_length (tb->ctors): 0;
9213 for (i = 0; i < num; ++i)
9214 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9215 num = tb->num_methods;
9217 for (i = 0; i < num; ++i)
9218 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9220 if (tb->interfaces) {
9221 klass->interface_count = mono_array_length (tb->interfaces);
9222 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9223 for (i = 0; i < klass->interface_count; ++i) {
9224 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9225 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9229 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9230 for (i = 0; i < klass->method.count; ++i)
9231 klass->methods [i]->slot = i;
9233 mono_class_setup_interface_offsets (klass);
9237 * The generic vtable is needed even if image->run is not set since some
9238 * runtime code like ves_icall_Type_GetMethodsByName depends on
9239 * method->slot being defined.
9243 * tb->methods could not be freed since it is used for determining
9244 * overrides during dynamic vtable construction.
9249 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9251 MonoReflectionTypeBuilder *tb;
9257 g_assert (klass->image->dynamic);
9259 if (!klass->reflection_info)
9262 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9264 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9268 for (i = 0; i < tb->num_methods; ++i) {
9269 MonoReflectionMethodBuilder *mb =
9270 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9271 if (mb->override_method)
9277 *overrides = g_new0 (MonoMethod*, onum * 2);
9280 for (i = 0; i < tb->num_methods; ++i) {
9281 MonoReflectionMethodBuilder *mb =
9282 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9283 if (mb->override_method) {
9284 (*overrides) [onum * 2] =
9285 mb->override_method->method;
9286 (*overrides) [onum * 2 + 1] =
9289 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9290 g_assert (mb->override_method->method);
9291 g_assert (mb->mhandle);
9298 *num_overrides = onum;
9302 typebuilder_setup_fields (MonoClass *klass)
9304 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9305 MonoReflectionFieldBuilder *fb;
9306 MonoClassField *field;
9311 klass->field.count = tb->num_fields;
9312 klass->field.first = 0;
9314 if (!klass->field.count)
9317 klass->fields = g_new0 (MonoClassField, klass->field.count);
9319 for (i = 0; i < klass->field.count; ++i) {
9320 fb = mono_array_get (tb->fields, gpointer, i);
9321 field = &klass->fields [i];
9322 field->name = mono_string_to_utf8 (fb->name);
9324 /* FIXME: handle type modifiers */
9325 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9326 field->type->attrs = fb->attrs;
9328 field->type = fb->type->type;
9330 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9331 field->data = mono_array_addr (fb->rva_data, char, 0);
9332 if (fb->offset != -1)
9333 field->offset = fb->offset;
9334 field->parent = klass;
9336 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9338 if (fb->def_value) {
9339 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9340 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9341 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9342 /* Copy the data from the blob since it might get realloc-ed */
9343 p = assembly->blob.data + idx;
9344 len = mono_metadata_decode_blob_size (p, &p2);
9346 field->data = g_malloc (len);
9347 memcpy ((gpointer)field->data, p, len);
9350 mono_class_layout_fields (klass);
9354 typebuilder_setup_properties (MonoClass *klass)
9356 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9357 MonoReflectionPropertyBuilder *pb;
9360 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9361 klass->property.first = 0;
9363 klass->properties = g_new0 (MonoProperty, klass->property.count);
9364 for (i = 0; i < klass->property.count; ++i) {
9365 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9366 klass->properties [i].parent = klass;
9367 klass->properties [i].attrs = pb->attrs;
9368 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9370 klass->properties [i].get = pb->get_method->mhandle;
9372 klass->properties [i].set = pb->set_method->mhandle;
9374 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9378 MonoReflectionEvent *
9379 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9381 MonoEvent *event = g_new0 (MonoEvent, 1);
9385 klass = my_mono_class_from_mono_type (tb->type.type);
9387 event->parent = klass;
9388 event->attrs = eb->attrs;
9389 event->name = mono_string_to_utf8 (eb->name);
9391 event->add = eb->add_method->mhandle;
9392 if (eb->remove_method)
9393 event->remove = eb->remove_method->mhandle;
9394 if (eb->raise_method)
9395 event->raise = eb->raise_method->mhandle;
9397 if (eb->other_methods) {
9398 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9399 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9400 MonoReflectionMethodBuilder *mb =
9401 mono_array_get (eb->other_methods,
9402 MonoReflectionMethodBuilder*, j);
9403 event->other [j] = mb->mhandle;
9407 return mono_event_get_object (mono_object_domain (tb), klass, event);
9411 typebuilder_setup_events (MonoClass *klass)
9413 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9414 MonoReflectionEventBuilder *eb;
9417 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9418 klass->event.first = 0;
9420 klass->events = g_new0 (MonoEvent, klass->event.count);
9421 for (i = 0; i < klass->event.count; ++i) {
9422 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9423 klass->events [i].parent = klass;
9424 klass->events [i].attrs = eb->attrs;
9425 klass->events [i].name = mono_string_to_utf8 (eb->name);
9427 klass->events [i].add = eb->add_method->mhandle;
9428 if (eb->remove_method)
9429 klass->events [i].remove = eb->remove_method->mhandle;
9430 if (eb->raise_method)
9431 klass->events [i].raise = eb->raise_method->mhandle;
9433 if (eb->other_methods) {
9434 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9435 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9436 MonoReflectionMethodBuilder *mb =
9437 mono_array_get (eb->other_methods,
9438 MonoReflectionMethodBuilder*, j);
9439 klass->events [i].other [j] = mb->mhandle;
9446 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9450 MonoReflectionType* res;
9453 MONO_ARCH_SAVE_REGS;
9455 domain = mono_object_domain (tb);
9456 klass = my_mono_class_from_mono_type (tb->type.type);
9458 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9461 * we need to lock the domain because the lock will be taken inside
9462 * So, we need to keep the locking order correct.
9464 mono_domain_lock (domain);
9465 mono_loader_lock ();
9466 if (klass->wastypebuilder) {
9467 mono_loader_unlock ();
9468 mono_domain_unlock (domain);
9469 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9472 * Fields to set in klass:
9473 * the various flags: delegate/unicode/contextbound etc.
9475 klass->flags = tb->attrs;
9476 klass->has_cctor = 1;
9477 klass->has_finalize = 1;
9480 if (!((MonoDynamicImage*)klass->image)->run) {
9481 if (klass->generic_container) {
9482 /* FIXME: The code below can't handle generic classes */
9483 klass->wastypebuilder = TRUE;
9484 mono_loader_unlock ();
9485 mono_domain_unlock (domain);
9486 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9491 /* enums are done right away */
9492 if (!klass->enumtype)
9493 ensure_runtime_vtable (klass);
9496 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9497 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9498 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9502 /* fields and object layout */
9503 if (klass->parent) {
9504 if (!klass->parent->size_inited)
9505 mono_class_init (klass->parent);
9506 klass->instance_size = klass->parent->instance_size;
9507 klass->class_size = 0;
9508 klass->min_align = klass->parent->min_align;
9509 /* if the type has no fields we won't call the field_setup
9510 * routine which sets up klass->has_references.
9512 klass->has_references |= klass->parent->has_references;
9514 klass->instance_size = sizeof (MonoObject);
9515 klass->min_align = 1;
9518 /* FIXME: handle packing_size and instance_size */
9519 typebuilder_setup_fields (klass);
9521 typebuilder_setup_properties (klass);
9523 typebuilder_setup_events (klass);
9525 klass->wastypebuilder = TRUE;
9526 mono_loader_unlock ();
9527 mono_domain_unlock (domain);
9529 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9530 g_assert (res != (MonoReflectionType*)tb);
9536 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9538 MonoGenericParam *param;
9541 MONO_ARCH_SAVE_REGS;
9543 param = g_new0 (MonoGenericParam, 1);
9545 if (gparam->mbuilder) {
9546 if (!gparam->mbuilder->generic_container)
9547 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9548 param->owner = gparam->mbuilder->generic_container;
9549 } else if (gparam->tbuilder) {
9550 g_assert (gparam->tbuilder->generic_container);
9551 param->owner = gparam->tbuilder->generic_container;
9554 param->method = NULL;
9555 param->name = mono_string_to_utf8 (gparam->name);
9556 param->num = gparam->index;
9558 image = &gparam->tbuilder->module->dynamic_image->image;
9559 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9561 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9563 gparam->type.type = g_new0 (MonoType, 1);
9564 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9565 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9566 gparam->type.type->data.generic_param = param;
9570 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9572 MonoDynamicImage *assembly = sig->module->dynamic_image;
9573 guint32 na = mono_array_length (sig->arguments);
9574 guint32 buflen, i, size;
9578 MONO_ARCH_SAVE_REGS;
9580 p = buf = g_malloc (size = 50 + na * 50);
9582 mono_metadata_encode_value (0x07, p, &p);
9583 mono_metadata_encode_value (na, p, &p);
9584 for (i = 0; i < na; ++i) {
9585 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9586 encode_reflection_type (assembly, type, p, &p);
9590 g_assert (buflen < size);
9591 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9592 p = mono_array_addr (result, char, 0);
9593 memcpy (p, buf, buflen);
9600 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9602 MonoDynamicImage *assembly = sig->module->dynamic_image;
9603 guint32 na = mono_array_length (sig->arguments);
9604 guint32 buflen, i, size;
9608 MONO_ARCH_SAVE_REGS;
9610 p = buf = g_malloc (size = 10 + na * 10);
9612 mono_metadata_encode_value (0x06, p, &p);
9613 for (i = 0; i < na; ++i) {
9614 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9615 encode_reflection_type (assembly, type, p, &p);
9619 g_assert (buflen < size);
9620 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9621 p = mono_array_addr (result, char, 0);
9622 memcpy (p, buf, buflen);
9629 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9631 ReflectionMethodBuilder rmb;
9632 MonoMethodSignature *sig;
9635 sig = dynamic_method_to_signature (mb);
9637 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9640 * Resolve references.
9643 * Every second entry in the refs array is reserved for storing handle_class,
9644 * which is needed by the ldtoken implementation in the JIT.
9646 rmb.nrefs = mb->nrefs;
9647 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9648 for (i = 0; i < mb->nrefs; i += 2) {
9649 MonoClass *handle_class;
9650 gpointer ref = resolve_object (mb->module->image,
9651 mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9654 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9657 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9658 rmb.refs [i + 1] = handle_class;
9662 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9666 /* ilgen is no longer needed */
9671 * mono_reflection_lookup_dynamic_token:
9673 * Finish the Builder object pointed to by TOKEN and return the corresponding
9674 * runtime structure. HANDLE_CLASS is set to the class required by
9678 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9680 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9683 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9686 return resolve_object (image, obj, handle_class);
9690 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9692 gpointer result = NULL;
9694 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9695 result = mono_string_intern ((MonoString*)obj);
9696 *handle_class = NULL;
9698 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9699 MonoReflectionType *tb = (MonoReflectionType*)obj;
9700 result = mono_class_from_mono_type (tb->type);
9701 *handle_class = mono_defaults.typehandle_class;
9703 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9704 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9705 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9706 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9707 result = ((MonoReflectionMethod*)obj)->method;
9708 *handle_class = mono_defaults.methodhandle_class;
9710 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9711 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9712 result = mb->mhandle;
9714 /* Type is not yet created */
9715 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9717 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9720 * Hopefully this has been filled in by calling CreateType() on the
9724 * TODO: This won't work if the application finishes another
9725 * TypeBuilder instance instead of this one.
9727 result = mb->mhandle;
9729 *handle_class = mono_defaults.methodhandle_class;
9730 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9731 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9733 result = cb->mhandle;
9735 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9737 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9738 result = cb->mhandle;
9740 *handle_class = mono_defaults.methodhandle_class;
9741 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9742 result = ((MonoReflectionField*)obj)->field;
9743 *handle_class = mono_defaults.fieldhandle_class;
9745 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9746 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9747 result = fb->handle;
9750 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9752 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9753 result = fb->handle;
9755 *handle_class = mono_defaults.fieldhandle_class;
9756 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9757 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9760 klass = tb->type.type->data.klass;
9761 if (klass->wastypebuilder) {
9762 /* Already created */
9766 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9767 result = tb->type.type->data.klass;
9770 *handle_class = mono_defaults.typehandle_class;
9771 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9772 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9773 MonoMethodSignature *sig;
9776 if (helper->arguments)
9777 nargs = mono_array_length (helper->arguments);
9781 sig = mono_metadata_signature_alloc (image, nargs);
9782 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9783 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9785 if (helper->call_conv == 0) /* unmanaged */
9786 sig->call_convention = helper->unmanaged_call_conv - 1;
9788 if (helper->call_conv & 0x02)
9789 sig->call_convention = MONO_CALL_VARARG;
9791 sig->call_convention = MONO_CALL_DEFAULT;
9793 sig->param_count = nargs;
9794 /* TODO: Copy type ? */
9795 sig->ret = helper->return_type->type;
9796 for (i = 0; i < nargs; ++i) {
9797 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9798 sig->params [i] = rt->type;
9802 *handle_class = NULL;
9803 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9804 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9805 /* Already created by the managed code */
9806 g_assert (method->mhandle);
9807 result = method->mhandle;
9808 *handle_class = mono_defaults.methodhandle_class;
9810 g_print (obj->vtable->klass->name);
9811 g_assert_not_reached ();
9817 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9818 const static guint32 declsec_flags_map[] = {
9819 0x00000000, /* empty */
9820 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9821 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9822 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9823 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9824 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9825 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9826 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9827 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9828 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9829 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9830 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9831 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9832 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9833 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9834 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9835 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9836 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9837 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9841 * Returns flags that includes all available security action associated to the handle.
9842 * @token: metadata token (either for a class or a method)
9843 * @image: image where resides the metadata.
9846 mono_declsec_get_flags (MonoImage *image, guint32 token)
9848 guint32 index = mono_metadata_declsec_from_index (image, token);
9849 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9854 for (i = index; i < t->rows; i++) {
9855 guint32 cols [MONO_DECL_SECURITY_SIZE];
9857 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9858 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9861 action = cols [MONO_DECL_SECURITY_ACTION];
9862 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9863 result |= declsec_flags_map [action];
9865 g_assert_not_reached ();
9872 * Get the security actions (in the form of flags) associated with the specified method.
9874 * @method: The method for which we want the declarative security flags.
9875 * Return the declarative security flags for the method (only).
9877 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9878 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9881 mono_declsec_flags_from_method (MonoMethod *method)
9883 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9884 /* FIXME: No cache (for the moment) */
9885 guint32 idx = mono_method_get_index (method);
9886 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9887 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9888 return mono_declsec_get_flags (method->klass->image, idx);
9894 * Get the security actions (in the form of flags) associated with the specified class.
9896 * @klass: The class for which we want the declarative security flags.
9897 * Return the declarative security flags for the class.
9899 * Note: We cache the flags inside the MonoClass structure as this will get
9900 * called very often (at least for each method).
9903 mono_declsec_flags_from_class (MonoClass *klass)
9905 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9906 if (!klass->declsec_flags) {
9907 guint32 idx = mono_metadata_token_index (klass->type_token);
9908 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9909 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9910 /* we cache the flags on classes */
9911 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9913 return klass->declsec_flags;
9919 * Get the security actions (in the form of flags) associated with the specified assembly.
9921 * @assembly: The assembly for which we want the declarative security flags.
9922 * Return the declarative security flags for the assembly.
9925 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9927 guint32 idx = 1; /* there is only one assembly */
9928 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9929 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9930 return mono_declsec_get_flags (assembly->image, idx);
9935 * Fill actions for the specific index (which may either be an encoded class token or
9936 * an encoded method token) from the metadata image.
9937 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9940 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9941 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9943 MonoBoolean result = FALSE;
9945 guint32 cols [MONO_DECL_SECURITY_SIZE];
9946 int index = mono_metadata_declsec_from_index (image, token);
9949 t = &image->tables [MONO_TABLE_DECLSECURITY];
9950 for (i = index; i < t->rows; i++) {
9951 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9953 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9956 /* if present only replace (class) permissions with method permissions */
9957 /* if empty accept either class or method permissions */
9958 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9959 if (!actions->demand.blob) {
9960 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9961 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9962 actions->demand.blob = (char*) (blob + 2);
9963 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9966 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9967 if (!actions->noncasdemand.blob) {
9968 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9969 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9970 actions->noncasdemand.blob = (char*) (blob + 2);
9971 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9974 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9975 if (!actions->demandchoice.blob) {
9976 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9977 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9978 actions->demandchoice.blob = (char*) (blob + 2);
9979 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9989 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9990 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9992 guint32 idx = mono_metadata_token_index (klass->type_token);
9993 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9994 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9995 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9999 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
10000 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10002 guint32 idx = mono_method_get_index (method);
10003 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10004 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10005 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10009 * Collect all actions (that requires to generate code in mini) assigned for
10010 * the specified method.
10011 * Note: Don't use the content of actions if the function return FALSE.
10014 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10016 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
10017 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10018 MonoBoolean result = FALSE;
10021 /* quick exit if no declarative security is present in the metadata */
10022 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10025 /* we want the original as the wrapper is "free" of the security informations */
10026 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10027 method = mono_marshal_method_from_wrapper (method);
10032 /* First we look for method-level attributes */
10033 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10034 mono_class_init (method->klass);
10035 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10037 result = mono_declsec_get_method_demands_params (method, demands,
10038 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10041 /* Here we use (or create) the class declarative cache to look for demands */
10042 flags = mono_declsec_flags_from_class (method->klass);
10043 if (flags & mask) {
10045 mono_class_init (method->klass);
10046 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10048 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10049 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10052 /* The boolean return value is used as a shortcut in case nothing needs to
10053 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10059 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10061 * Note: Don't use the content of actions if the function return FALSE.
10064 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10066 MonoBoolean result = FALSE;
10069 /* quick exit if no declarative security is present in the metadata */
10070 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10073 /* we want the original as the wrapper is "free" of the security informations */
10074 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10075 method = mono_marshal_method_from_wrapper (method);
10080 /* results are independant - zeroize both */
10081 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10082 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10084 /* First we look for method-level attributes */
10085 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10086 mono_class_init (method->klass);
10088 result = mono_declsec_get_method_demands_params (method, cmethod,
10089 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10092 /* Here we use (or create) the class declarative cache to look for demands */
10093 flags = mono_declsec_flags_from_class (method->klass);
10094 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10095 mono_class_init (method->klass);
10097 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10098 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10105 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10107 * @klass The inherited class - this is the class that provides the security check (attributes)
10109 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10111 * Note: Don't use the content of actions if the function return FALSE.
10114 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10116 MonoBoolean result = FALSE;
10119 /* quick exit if no declarative security is present in the metadata */
10120 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10123 /* Here we use (or create) the class declarative cache to look for demands */
10124 flags = mono_declsec_flags_from_class (klass);
10125 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10126 mono_class_init (klass);
10127 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10129 result |= mono_declsec_get_class_demands_params (klass, demands,
10130 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10137 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10139 * Note: Don't use the content of actions if the function return FALSE.
10142 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10144 /* quick exit if no declarative security is present in the metadata */
10145 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10148 /* we want the original as the wrapper is "free" of the security informations */
10149 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10150 method = mono_marshal_method_from_wrapper (method);
10155 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10156 mono_class_init (method->klass);
10157 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10159 return mono_declsec_get_method_demands_params (method, demands,
10160 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10167 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10169 guint32 cols [MONO_DECL_SECURITY_SIZE];
10173 int index = mono_metadata_declsec_from_index (image, token);
10177 t = &image->tables [MONO_TABLE_DECLSECURITY];
10178 for (i = index; i < t->rows; i++) {
10179 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10181 /* shortcut - index are ordered */
10182 if (token != cols [MONO_DECL_SECURITY_PARENT])
10185 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10186 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10187 entry->blob = (char*) (metadata + 2);
10188 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10197 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10199 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10200 guint32 idx = mono_method_get_index (method);
10201 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10202 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10203 return get_declsec_action (method->klass->image, idx, action, entry);
10209 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10212 guint32 flags = mono_declsec_flags_from_class (klass);
10213 if (declsec_flags_map [action] & flags) {
10214 guint32 idx = mono_metadata_token_index (klass->type_token);
10215 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10216 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10217 return get_declsec_action (klass->image, idx, action, entry);
10223 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10225 guint32 idx = 1; /* there is only one assembly */
10226 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10227 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10229 return get_declsec_action (assembly->image, idx, action, entry);
10233 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10235 MonoObject *res, *exc;
10237 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10238 static MonoMethod *method = NULL;
10240 if (!System_Reflection_Emit_TypeBuilder) {
10241 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10242 g_assert (System_Reflection_Emit_TypeBuilder);
10244 if (method == NULL) {
10245 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10250 * The result of mono_type_get_object () might be a System.MonoType but we
10251 * need a TypeBuilder so use klass->reflection_info.
10253 g_assert (klass->reflection_info);
10254 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10256 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10258 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10262 return *(MonoBoolean*)mono_object_unbox (res);