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 g_assert (ex_info->handlers);
877 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
878 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
879 clause = &(clauses [clause_index]);
881 clause->flags = ex_block->type;
882 clause->try_offset = ex_info->start;
884 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
885 clause->try_len = finally_start - ex_info->start;
887 clause->try_len = ex_info->len;
888 clause->handler_offset = ex_block->start;
889 clause->handler_len = ex_block->len;
890 if (ex_block->extype) {
891 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
893 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
894 clause->data.filter_offset = ex_block->filter_offset;
896 clause->data.filter_offset = 0;
898 finally_start = ex_block->start + ex_block->len;
908 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
914 gint32 num_locals = 0;
915 gint32 num_exception = 0;
918 char fat_header [12];
921 guint32 local_sig = 0;
922 guint32 header_size = 12;
925 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
926 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
930 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
932 code = mb->ilgen->code;
933 code_size = mb->ilgen->code_len;
934 max_stack = mb->ilgen->max_stack;
935 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
936 if (mb->ilgen->ex_handlers)
937 num_exception = method_count_clauses (mb->ilgen);
941 char *name = mono_string_to_utf8 (mb->name);
942 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
943 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
946 mono_raise_exception (exception);
949 code_size = mono_array_length (code);
950 max_stack = 8; /* we probably need to run a verifier on the code... */
953 stream_data_align (&assembly->code);
955 /* check for exceptions, maxstack, locals */
956 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
958 if (code_size < 64 && !(code_size & 1)) {
959 flags = (code_size << 2) | 0x2;
960 } else if (code_size < 32 && (code_size & 1)) {
961 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
965 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
966 /* add to the fixup todo list */
967 if (mb->ilgen && mb->ilgen->num_token_fixups)
968 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
969 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
970 return assembly->text_rva + idx;
974 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
976 * FIXME: need to set also the header size in fat_flags.
977 * (and more sects and init locals flags)
981 fat_flags |= METHOD_HEADER_MORE_SECTS;
983 fat_flags |= METHOD_HEADER_INIT_LOCALS;
984 fat_header [0] = fat_flags;
985 fat_header [1] = (header_size / 4 ) << 4;
986 short_value = GUINT16_TO_LE (max_stack);
987 memcpy (fat_header + 2, &short_value, 2);
988 int_value = GUINT32_TO_LE (code_size);
989 memcpy (fat_header + 4, &int_value, 4);
990 int_value = GUINT32_TO_LE (local_sig);
991 memcpy (fat_header + 8, &int_value, 4);
992 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
993 /* add to the fixup todo list */
994 if (mb->ilgen && mb->ilgen->num_token_fixups)
995 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
997 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
999 unsigned char sheader [4];
1000 MonoILExceptionInfo * ex_info;
1001 MonoILExceptionBlock * ex_block;
1004 stream_data_align (&assembly->code);
1005 /* always use fat format for now */
1006 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1007 num_exception *= 6 * sizeof (guint32);
1008 num_exception += 4; /* include the size of the header */
1009 sheader [1] = num_exception & 0xff;
1010 sheader [2] = (num_exception >> 8) & 0xff;
1011 sheader [3] = (num_exception >> 16) & 0xff;
1012 mono_image_add_stream_data (&assembly->code, sheader, 4);
1013 /* fat header, so we are already aligned */
1015 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1016 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1017 if (ex_info->handlers) {
1018 int finally_start = ex_info->start + ex_info->len;
1019 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1021 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1023 val = GUINT32_TO_LE (ex_block->type);
1024 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1026 val = GUINT32_TO_LE (ex_info->start);
1027 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1028 /* need fault, too, probably */
1029 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1030 val = GUINT32_TO_LE (finally_start - ex_info->start);
1032 val = GUINT32_TO_LE (ex_info->len);
1033 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1034 /* handler offset */
1035 val = GUINT32_TO_LE (ex_block->start);
1036 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1038 val = GUINT32_TO_LE (ex_block->len);
1039 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1040 finally_start = ex_block->start + ex_block->len;
1041 if (ex_block->extype) {
1042 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1044 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1045 val = ex_block->filter_offset;
1049 val = GUINT32_TO_LE (val);
1050 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1051 /*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",
1052 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);*/
1055 g_error ("No clauses for ex info block %d", i);
1059 return assembly->text_rva + idx;
1063 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1066 MonoDynamicTable *table;
1069 table = &assembly->tables [table_idx];
1071 g_assert (col < table->columns);
1073 values = table->values + table->columns;
1074 for (i = 1; i <= table->rows; ++i) {
1075 if (values [col] == token)
1077 values += table->columns;
1082 static GHashTable *dynamic_custom_attrs = NULL;
1085 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1087 /* FIXME: Need to do more checks */
1088 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1089 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1091 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1098 static MonoCustomAttrInfo*
1099 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1101 int i, index, count, not_visible;
1102 MonoCustomAttrInfo *ainfo;
1103 MonoReflectionCustomAttr *cattr;
1107 /* FIXME: check in assembly the Run flag is set */
1109 count = mono_array_length (cattrs);
1111 /* Skip nonpublic attributes since MS.NET seems to do the same */
1112 /* FIXME: This needs to be done more globally */
1114 for (i = 0; i < count; ++i) {
1115 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1116 if (!custom_attr_visible (image, cattr))
1119 count -= not_visible;
1121 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1123 ainfo->image = image;
1124 ainfo->num_attrs = count;
1126 for (i = 0; i < count; ++i) {
1127 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1128 if (custom_attr_visible (image, cattr)) {
1129 ainfo->attrs [index].ctor = cattr->ctor->method;
1130 /* FIXME: might want to memdup the data here */
1131 ainfo->attrs [index].data = mono_array_addr (cattr->data, char, 0);
1132 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1141 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1143 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1148 if (!dynamic_custom_attrs)
1149 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1151 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1152 ainfo->cached = TRUE;
1156 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1158 /* they are cached, so we don't free them */
1159 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1165 * idx is the table index of the object
1166 * type is one of MONO_CUSTOM_ATTR_*
1169 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1171 MonoDynamicTable *table;
1172 MonoReflectionCustomAttr *cattr;
1174 guint32 count, i, token;
1176 char *p = blob_size;
1178 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1181 count = mono_array_length (cattrs);
1182 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1183 table->rows += count;
1184 alloc_table (table, table->rows);
1185 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1186 idx <<= MONO_CUSTOM_ATTR_BITS;
1188 for (i = 0; i < count; ++i) {
1189 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1190 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1191 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1192 type = mono_metadata_token_index (token);
1193 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1194 switch (mono_metadata_token_table (token)) {
1195 case MONO_TABLE_METHOD:
1196 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1198 case MONO_TABLE_MEMBERREF:
1199 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1202 g_warning ("got wrong token in custom attr");
1205 values [MONO_CUSTOM_ATTR_TYPE] = type;
1207 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1208 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1209 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1210 values += MONO_CUSTOM_ATTR_SIZE;
1216 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1218 MonoDynamicTable *table;
1220 guint32 count, i, idx;
1221 MonoReflectionPermissionSet *perm;
1226 count = mono_array_length (permissions);
1227 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1228 table->rows += count;
1229 alloc_table (table, table->rows);
1231 for (i = 0; i < mono_array_length (permissions); ++i) {
1232 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1234 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1236 idx = mono_metadata_token_index (parent_token);
1237 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1238 switch (mono_metadata_token_table (parent_token)) {
1239 case MONO_TABLE_TYPEDEF:
1240 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1242 case MONO_TABLE_METHOD:
1243 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1245 case MONO_TABLE_ASSEMBLY:
1246 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1249 g_assert_not_reached ();
1252 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1253 values [MONO_DECL_SECURITY_PARENT] = idx;
1254 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1261 * Fill in the MethodDef and ParamDef tables for a method.
1262 * This is used for both normal methods and constructors.
1265 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1267 MonoDynamicTable *table;
1272 /* room in this table is already allocated */
1273 table = &assembly->tables [MONO_TABLE_METHOD];
1274 *mb->table_idx = table->next_idx ++;
1275 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1276 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1277 name = mono_string_to_utf8 (mb->name);
1278 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1280 values [MONO_METHOD_FLAGS] = mb->attrs;
1281 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1282 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1283 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1285 table = &assembly->tables [MONO_TABLE_PARAM];
1286 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1288 mono_image_add_decl_security (assembly,
1289 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1292 MonoDynamicTable *mtable;
1295 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1296 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1299 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1300 if (mono_array_get (mb->pinfo, gpointer, i))
1303 table->rows += count;
1304 alloc_table (table, table->rows);
1305 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1306 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1307 MonoReflectionParamBuilder *pb;
1308 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1309 values [MONO_PARAM_FLAGS] = pb->attrs;
1310 values [MONO_PARAM_SEQUENCE] = i;
1311 if (pb->name != NULL) {
1312 name = mono_string_to_utf8 (pb->name);
1313 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1316 values [MONO_PARAM_NAME] = 0;
1318 values += MONO_PARAM_SIZE;
1319 if (pb->marshal_info) {
1321 alloc_table (mtable, mtable->rows);
1322 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1323 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1324 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1326 pb->table_idx = table->next_idx++;
1327 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1328 guint32 field_type = 0;
1329 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1331 alloc_table (mtable, mtable->rows);
1332 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1333 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1334 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1335 mvalues [MONO_CONSTANT_TYPE] = field_type;
1336 mvalues [MONO_CONSTANT_PADDING] = 0;
1344 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1346 rmb->ilgen = mb->ilgen;
1347 rmb->rtype = mb->rtype;
1348 rmb->parameters = mb->parameters;
1349 rmb->generic_params = mb->generic_params;
1350 rmb->generic_container = mb->generic_container;
1351 rmb->opt_types = NULL;
1352 rmb->pinfo = mb->pinfo;
1353 rmb->attrs = mb->attrs;
1354 rmb->iattrs = mb->iattrs;
1355 rmb->call_conv = mb->call_conv;
1356 rmb->code = mb->code;
1357 rmb->type = mb->type;
1358 rmb->name = mb->name;
1359 rmb->table_idx = &mb->table_idx;
1360 rmb->init_locals = mb->init_locals;
1361 rmb->return_modreq = mb->return_modreq;
1362 rmb->return_modopt = mb->return_modopt;
1363 rmb->param_modreq = mb->param_modreq;
1364 rmb->param_modopt = mb->param_modopt;
1365 rmb->permissions = mb->permissions;
1366 rmb->mhandle = mb->mhandle;
1371 rmb->charset = mb->charset;
1372 rmb->extra_flags = mb->extra_flags;
1373 rmb->native_cc = mb->native_cc;
1374 rmb->dllentry = mb->dllentry;
1380 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1382 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1384 rmb->ilgen = mb->ilgen;
1385 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1386 rmb->parameters = mb->parameters;
1387 rmb->generic_params = NULL;
1388 rmb->generic_container = NULL;
1389 rmb->opt_types = NULL;
1390 rmb->pinfo = mb->pinfo;
1391 rmb->attrs = mb->attrs;
1392 rmb->iattrs = mb->iattrs;
1393 rmb->call_conv = mb->call_conv;
1395 rmb->type = mb->type;
1396 rmb->name = mono_string_new (mono_domain_get (), name);
1397 rmb->table_idx = &mb->table_idx;
1398 rmb->init_locals = mb->init_locals;
1399 rmb->return_modreq = NULL;
1400 rmb->return_modopt = NULL;
1401 rmb->param_modreq = mb->param_modreq;
1402 rmb->param_modopt = mb->param_modopt;
1403 rmb->permissions = mb->permissions;
1404 rmb->mhandle = mb->mhandle;
1410 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1412 rmb->ilgen = mb->ilgen;
1413 rmb->rtype = mb->rtype;
1414 rmb->parameters = mb->parameters;
1415 rmb->generic_params = NULL;
1416 rmb->generic_container = NULL;
1417 rmb->opt_types = NULL;
1419 rmb->attrs = mb->attrs;
1421 rmb->call_conv = mb->call_conv;
1424 rmb->name = mb->name;
1425 rmb->table_idx = NULL;
1426 rmb->init_locals = mb->init_locals;
1427 rmb->return_modreq = NULL;
1428 rmb->return_modopt = NULL;
1429 rmb->param_modreq = NULL;
1430 rmb->param_modopt = NULL;
1431 rmb->permissions = NULL;
1432 rmb->mhandle = mb->mhandle;
1438 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1440 MonoDynamicTable *table;
1443 ReflectionMethodBuilder rmb;
1446 reflection_methodbuilder_from_method_builder (&rmb, mb);
1448 mono_image_basic_method (&rmb, assembly);
1449 mb->table_idx = *rmb.table_idx;
1451 if (mb->dll) { /* It's a P/Invoke method */
1453 /* map CharSet values to on-disk values */
1454 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1455 int extra_flags = mb->extra_flags;
1456 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1458 alloc_table (table, table->rows);
1459 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1461 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1462 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1464 name = mono_string_to_utf8 (mb->dllentry);
1466 name = mono_string_to_utf8 (mb->name);
1467 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1469 name = mono_string_to_utf8 (mb->dll);
1470 moduleref = string_heap_insert (&assembly->sheap, name);
1472 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1473 table = &assembly->tables [MONO_TABLE_MODULEREF];
1475 alloc_table (table, table->rows);
1476 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1477 values [MONO_IMPLMAP_SCOPE] = table->rows;
1481 if (mb->override_method) {
1482 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1484 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1486 alloc_table (table, table->rows);
1487 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1488 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1489 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1491 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1492 switch (mono_metadata_token_table (tok)) {
1493 case MONO_TABLE_MEMBERREF:
1494 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1496 case MONO_TABLE_METHOD:
1497 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1500 g_assert_not_reached ();
1502 values [MONO_METHODIMPL_DECLARATION] = tok;
1505 if (mb->generic_params) {
1506 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1507 table->rows += mono_array_length (mb->generic_params);
1508 alloc_table (table, table->rows);
1509 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1510 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1512 mono_image_get_generic_param_info (
1513 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1520 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1522 ReflectionMethodBuilder rmb;
1524 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1526 mono_image_basic_method (&rmb, assembly);
1527 mb->table_idx = *rmb.table_idx;
1531 type_get_fully_qualified_name (MonoType *type)
1533 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1537 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1541 klass = my_mono_class_from_mono_type (type);
1543 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1544 ta = klass->image->assembly;
1545 if (ta->dynamic || (ta == ass))
1546 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1548 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1552 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1554 char blob_size [64];
1555 char *b = blob_size;
1560 if (!assembly->save)
1563 p = buf = g_malloc (256);
1565 mono_metadata_encode_value (0x06, p, &p);
1566 /* encode custom attributes before the type */
1567 encode_type (assembly, type, p, &p);
1568 g_assert (p-buf < 256);
1569 mono_metadata_encode_value (p-buf, b, &b);
1570 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1576 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1578 char blob_size [64];
1579 char *b = blob_size;
1584 p = buf = g_malloc (256);
1586 mono_metadata_encode_value (0x06, p, &p);
1587 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1588 /* encode custom attributes before the type */
1589 encode_reflection_type (assembly, fb->type, p, &p);
1590 g_assert (p-buf < 256);
1591 mono_metadata_encode_value (p-buf, b, &b);
1592 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1598 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1599 char blob_size [64];
1600 char *b = blob_size;
1603 guint32 idx = 0, len = 0, dummy = 0;
1605 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1606 guint32 fpa_double [2];
1611 p = buf = g_malloc (64);
1613 *ret_type = MONO_TYPE_CLASS;
1615 box_val = (char*)&dummy;
1617 box_val = ((char*)val) + sizeof (MonoObject);
1618 *ret_type = val->vtable->klass->byval_arg.type;
1621 switch (*ret_type) {
1622 case MONO_TYPE_BOOLEAN:
1627 case MONO_TYPE_CHAR:
1644 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1645 fpa_p = (guint32*)box_val;
1646 fpa_double [0] = fpa_p [1];
1647 fpa_double [1] = fpa_p [0];
1648 box_val = (char*)fpa_double;
1652 case MONO_TYPE_VALUETYPE:
1653 if (val->vtable->klass->enumtype) {
1654 *ret_type = val->vtable->klass->enum_basetype->type;
1657 g_error ("we can't encode valuetypes");
1658 case MONO_TYPE_CLASS:
1660 case MONO_TYPE_STRING: {
1661 MonoString *str = (MonoString*)val;
1662 /* there is no signature */
1663 len = str->length * 2;
1664 mono_metadata_encode_value (len, b, &b);
1665 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1667 char *swapped = g_malloc (2 * mono_string_length (str));
1668 const char *p = (const char*)mono_string_chars (str);
1670 swap_with_size (swapped, p, 2, mono_string_length (str));
1671 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1675 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1682 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1685 /* there is no signature */
1686 mono_metadata_encode_value (len, b, &b);
1687 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1688 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1689 swap_with_size (blob_size, box_val, len, 1);
1690 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1692 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1700 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1701 char blob_size [64];
1702 char *b = blob_size;
1703 char *p, *buf, *str;
1704 guint32 idx, len, bufsize = 256;
1706 p = buf = g_malloc (bufsize);
1708 mono_metadata_encode_value (minfo->type, p, &p);
1710 switch (minfo->type) {
1711 case MONO_NATIVE_BYVALTSTR:
1712 case MONO_NATIVE_BYVALARRAY:
1713 mono_metadata_encode_value (minfo->count, p, &p);
1715 case MONO_NATIVE_LPARRAY:
1716 if (minfo->eltype || minfo->has_size) {
1717 mono_metadata_encode_value (minfo->eltype, p, &p);
1718 if (minfo->has_size) {
1719 if (minfo->param_num != -1)
1720 mono_metadata_encode_value (minfo->param_num, p, &p);
1722 mono_metadata_encode_value (0, p, &p);
1723 if (minfo->count != -1)
1724 mono_metadata_encode_value (minfo->count, p, &p);
1726 mono_metadata_encode_value (0, p, &p);
1728 /* LAMESPEC: ElemMult is undocumented */
1729 if (minfo->param_num != -1)
1730 mono_metadata_encode_value (1, p, &p);
1732 mono_metadata_encode_value (0, p, &p);
1736 case MONO_NATIVE_CUSTOM:
1738 str = mono_string_to_utf8 (minfo->guid);
1740 mono_metadata_encode_value (len, p, &p);
1741 memcpy (p, str, len);
1745 mono_metadata_encode_value (0, p, &p);
1747 /* native type name */
1748 mono_metadata_encode_value (0, p, &p);
1749 /* custom marshaler type name */
1750 if (minfo->marshaltype || minfo->marshaltyperef) {
1751 if (minfo->marshaltyperef)
1752 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1754 str = mono_string_to_utf8 (minfo->marshaltype);
1756 mono_metadata_encode_value (len, p, &p);
1757 if (p + len >= buf + bufsize) {
1760 buf = g_realloc (buf, bufsize);
1763 memcpy (p, str, len);
1767 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1768 mono_metadata_encode_value (0, p, &p);
1770 if (minfo->mcookie) {
1771 str = mono_string_to_utf8 (minfo->mcookie);
1773 mono_metadata_encode_value (len, p, &p);
1774 if (p + len >= buf + bufsize) {
1777 buf = g_realloc (buf, bufsize);
1780 memcpy (p, str, len);
1784 mono_metadata_encode_value (0, p, &p);
1791 mono_metadata_encode_value (len, b, &b);
1792 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1798 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1800 MonoDynamicTable *table;
1804 /* maybe this fixup should be done in the C# code */
1805 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1806 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1807 table = &assembly->tables [MONO_TABLE_FIELD];
1808 fb->table_idx = table->next_idx ++;
1809 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1810 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1811 name = mono_string_to_utf8 (fb->name);
1812 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1814 values [MONO_FIELD_FLAGS] = fb->attrs;
1815 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1817 if (fb->offset != -1) {
1818 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1820 alloc_table (table, table->rows);
1821 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1822 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1823 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1825 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1826 guint32 field_type = 0;
1827 table = &assembly->tables [MONO_TABLE_CONSTANT];
1829 alloc_table (table, table->rows);
1830 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1831 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1832 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1833 values [MONO_CONSTANT_TYPE] = field_type;
1834 values [MONO_CONSTANT_PADDING] = 0;
1836 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1838 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1840 alloc_table (table, table->rows);
1841 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1842 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1844 * We store it in the code section because it's simpler for now.
1847 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1849 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1850 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1852 if (fb->marshal_info) {
1853 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1855 alloc_table (table, table->rows);
1856 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1857 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1858 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1863 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1867 char *b = blob_size;
1868 guint32 nparams = 0;
1869 MonoReflectionMethodBuilder *mb = fb->get_method;
1870 MonoReflectionMethodBuilder *smb = fb->set_method;
1871 guint32 idx, i, size;
1873 if (mb && mb->parameters)
1874 nparams = mono_array_length (mb->parameters);
1875 if (!mb && smb && smb->parameters)
1876 nparams = mono_array_length (smb->parameters) - 1;
1877 size = 24 + nparams * 10;
1878 buf = p = g_malloc (size);
1881 mono_metadata_encode_value (nparams, p, &p);
1883 encode_reflection_type (assembly, mb->rtype, p, &p);
1884 for (i = 0; i < nparams; ++i) {
1885 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1886 encode_reflection_type (assembly, pt, p, &p);
1889 /* the property type is the last param */
1890 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1891 for (i = 0; i < nparams; ++i) {
1892 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1893 encode_reflection_type (assembly, pt, p, &p);
1897 encode_reflection_type (assembly, fb->type, p, &p);
1901 g_assert (p - buf < size);
1902 mono_metadata_encode_value (p-buf, b, &b);
1903 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1909 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1911 MonoDynamicTable *table;
1914 guint num_methods = 0;
1918 * we need to set things in the following tables:
1919 * PROPERTYMAP (info already filled in _get_type_info ())
1920 * PROPERTY (rows already preallocated in _get_type_info ())
1921 * METHOD (method info already done with the generic method code)
1924 table = &assembly->tables [MONO_TABLE_PROPERTY];
1925 pb->table_idx = table->next_idx ++;
1926 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1927 name = mono_string_to_utf8 (pb->name);
1928 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1930 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1931 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1933 /* FIXME: we still don't handle 'other' methods */
1934 if (pb->get_method) num_methods ++;
1935 if (pb->set_method) num_methods ++;
1937 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1938 table->rows += num_methods;
1939 alloc_table (table, table->rows);
1941 if (pb->get_method) {
1942 semaidx = table->next_idx ++;
1943 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1944 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1945 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1946 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1948 if (pb->set_method) {
1949 semaidx = table->next_idx ++;
1950 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1951 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1952 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1953 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1958 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1960 MonoDynamicTable *table;
1963 guint num_methods = 0;
1967 * we need to set things in the following tables:
1968 * EVENTMAP (info already filled in _get_type_info ())
1969 * EVENT (rows already preallocated in _get_type_info ())
1970 * METHOD (method info already done with the generic method code)
1973 table = &assembly->tables [MONO_TABLE_EVENT];
1974 eb->table_idx = table->next_idx ++;
1975 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1976 name = mono_string_to_utf8 (eb->name);
1977 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1979 values [MONO_EVENT_FLAGS] = eb->attrs;
1980 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1983 * FIXME: we still don't handle 'other' methods
1985 if (eb->add_method) num_methods ++;
1986 if (eb->remove_method) num_methods ++;
1987 if (eb->raise_method) num_methods ++;
1989 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1990 table->rows += num_methods;
1991 alloc_table (table, table->rows);
1993 if (eb->add_method) {
1994 semaidx = table->next_idx ++;
1995 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1996 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1997 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1998 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2000 if (eb->remove_method) {
2001 semaidx = table->next_idx ++;
2002 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2003 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2004 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2005 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2007 if (eb->raise_method) {
2008 semaidx = table->next_idx ++;
2009 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2010 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2011 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2012 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2017 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2019 MonoDynamicTable *table;
2020 guint32 num_constraints, i;
2024 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2025 num_constraints = gparam->iface_constraints ?
2026 mono_array_length (gparam->iface_constraints) : 0;
2027 table->rows += num_constraints;
2028 if (gparam->base_type)
2030 alloc_table (table, table->rows);
2032 if (gparam->base_type) {
2033 table_idx = table->next_idx ++;
2034 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2036 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2037 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2038 assembly, gparam->base_type->type);
2041 for (i = 0; i < num_constraints; i++) {
2042 MonoReflectionType *constraint = mono_array_get (
2043 gparam->iface_constraints, gpointer, i);
2045 table_idx = table->next_idx ++;
2046 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2048 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2049 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2050 assembly, constraint->type);
2055 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2057 GenericParamTableEntry *entry;
2060 * The GenericParam table must be sorted according to the `owner' field.
2061 * We need to do this sorting prior to writing the GenericParamConstraint
2062 * table, since we have to use the final GenericParam table indices there
2063 * and they must also be sorted.
2066 entry = g_new0 (GenericParamTableEntry, 1);
2067 entry->owner = owner;
2068 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2070 g_ptr_array_add (assembly->gen_params, entry);
2074 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2076 MonoDynamicTable *table;
2077 MonoGenericParam *param;
2081 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2082 table_idx = table->next_idx ++;
2083 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2085 param = entry->gparam->type.type->data.generic_param;
2087 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2088 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2089 values [MONO_GENERICPARAM_NUMBER] = param->num;
2090 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2092 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2094 encode_constraints (entry->gparam, table_idx, assembly);
2098 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2100 MonoDynamicTable *table;
2103 guint32 cols [MONO_ASSEMBLY_SIZE];
2107 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2110 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2111 table = &assembly->tables [MONO_TABLE_MODULEREF];
2112 token = table->next_idx ++;
2114 alloc_table (table, table->rows);
2115 values = table->values + token * MONO_MODULEREF_SIZE;
2116 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2118 token <<= MONO_RESOLTION_SCOPE_BITS;
2119 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2120 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2125 if (image->assembly->dynamic)
2127 memset (cols, 0, sizeof (cols));
2129 /* image->assembly->image is the manifest module */
2130 image = image->assembly->image;
2131 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2134 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2135 token = table->next_idx ++;
2137 alloc_table (table, table->rows);
2138 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2139 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2140 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2141 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2142 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2143 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2144 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2145 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2146 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2148 if (strcmp ("", image->assembly->aname.culture)) {
2149 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2150 image->assembly->aname.culture);
2153 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2154 guchar pubtoken [9];
2156 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2157 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2159 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2161 token <<= MONO_RESOLTION_SCOPE_BITS;
2162 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2163 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2168 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2170 MonoDynamicTable *table;
2176 char *b = blob_size;
2178 switch (type->type) {
2179 case MONO_TYPE_FNPTR:
2181 case MONO_TYPE_SZARRAY:
2182 case MONO_TYPE_ARRAY:
2184 case MONO_TYPE_MVAR:
2185 case MONO_TYPE_GENERICINST:
2186 encode_type (assembly, type, p, &p);
2188 case MONO_TYPE_CLASS:
2189 case MONO_TYPE_VALUETYPE: {
2190 MonoClass *k = mono_class_from_mono_type (type);
2191 if (!k || !k->generic_class)
2193 encode_generic_class (assembly, k->generic_class, p, &p);
2200 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2201 if (assembly->save) {
2202 g_assert (p-sig < 128);
2203 mono_metadata_encode_value (p-sig, b, &b);
2204 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2205 alloc_table (table, table->rows + 1);
2206 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2207 values [MONO_TYPESPEC_SIGNATURE] = token;
2210 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2211 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2217 * Despite the name, we handle also TypeSpec (with the above helper).
2220 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2222 MonoDynamicTable *table;
2224 guint32 token, scope, enclosing;
2227 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2230 token = create_typespec (assembly, type);
2233 klass = my_mono_class_from_mono_type (type);
2235 klass = mono_class_from_mono_type (type);
2238 * If it's in the same module and not a generic type parameter:
2240 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2241 (type->type != MONO_TYPE_MVAR)) {
2242 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2243 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2244 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2248 if (klass->nested_in) {
2249 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2250 /* get the typeref idx of the enclosing type */
2251 enclosing >>= MONO_TYPEDEFORREF_BITS;
2252 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2254 scope = resolution_scope_from_image (assembly, klass->image);
2256 table = &assembly->tables [MONO_TABLE_TYPEREF];
2257 if (assembly->save) {
2258 alloc_table (table, table->rows + 1);
2259 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2260 values [MONO_TYPEREF_SCOPE] = scope;
2261 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2262 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2264 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2265 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2267 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2272 * Insert a memberef row into the metadata: the token that point to the memberref
2273 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2274 * mono_image_get_fieldref_token()).
2275 * The sig param is an index to an already built signature.
2278 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2280 MonoDynamicTable *table;
2282 guint32 token, pclass;
2285 parent = mono_image_typedef_or_ref (assembly, type);
2286 switch (parent & MONO_TYPEDEFORREF_MASK) {
2287 case MONO_TYPEDEFORREF_TYPEREF:
2288 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2290 case MONO_TYPEDEFORREF_TYPESPEC:
2291 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2293 case MONO_TYPEDEFORREF_TYPEDEF:
2294 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2297 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2300 /* extract the index */
2301 parent >>= MONO_TYPEDEFORREF_BITS;
2303 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2305 if (assembly->save) {
2306 alloc_table (table, table->rows + 1);
2307 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2308 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2309 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2310 values [MONO_MEMBERREF_SIGNATURE] = sig;
2313 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2320 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2323 MonoMethodSignature *sig;
2325 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2330 * A methodref signature can't contain an unmanaged calling convention.
2332 sig = mono_metadata_signature_dup (mono_method_signature (method));
2333 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2334 sig->call_convention = MONO_CALL_DEFAULT;
2335 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2336 method->name, method_encode_signature (assembly, sig));
2338 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2343 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2344 const gchar *name, guint32 sig)
2346 MonoDynamicTable *table;
2350 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2352 if (assembly->save) {
2353 alloc_table (table, table->rows + 1);
2354 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2355 values [MONO_MEMBERREF_CLASS] = original;
2356 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2357 values [MONO_MEMBERREF_SIGNATURE] = sig;
2360 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2367 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2370 ReflectionMethodBuilder rmb;
2372 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2376 reflection_methodbuilder_from_method_builder (&rmb, mb);
2378 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2379 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2380 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2385 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2388 ReflectionMethodBuilder rmb;
2390 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2394 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2396 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2397 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2398 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2403 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2408 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2411 g_assert (f->field->parent);
2412 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2413 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2414 f->field->name, fieldref_encode_signature (assembly, type));
2415 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2420 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2425 guint32 nparams = gmethod->inst->type_argc;
2426 guint32 size = 10 + nparams * 30;
2429 char *b = blob_size;
2431 if (!assembly->save)
2434 p = buf = g_malloc (size);
2436 * FIXME: vararg, explicit_this, differenc call_conv values...
2438 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2439 mono_metadata_encode_value (nparams, p, &p);
2441 for (i = 0; i < nparams; i++)
2442 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2445 g_assert (p - buf < size);
2446 mono_metadata_encode_value (p-buf, b, &b);
2447 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2453 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2455 MonoDynamicTable *table;
2457 guint32 token, mtoken = 0, sig;
2458 MonoMethodInflated *imethod;
2459 MonoMethod *declaring;
2461 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2463 g_assert (method->is_inflated);
2464 method = mono_get_inflated_method (method);
2465 imethod = (MonoMethodInflated *) method;
2466 declaring = imethod->declaring;
2468 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2469 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2471 if (!mono_method_signature (declaring)->generic_param_count)
2474 switch (mono_metadata_token_table (mtoken)) {
2475 case MONO_TABLE_MEMBERREF:
2476 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2478 case MONO_TABLE_METHOD:
2479 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2482 g_assert_not_reached ();
2485 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2487 if (assembly->save) {
2488 alloc_table (table, table->rows + 1);
2489 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2490 values [MONO_METHODSPEC_METHOD] = mtoken;
2491 values [MONO_METHODSPEC_SIGNATURE] = sig;
2494 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2501 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2503 MonoMethodInflated *imethod;
2504 MonoMethod *inflated;
2507 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2511 g_assert (method->is_inflated);
2512 inflated = mono_get_inflated_method (method);
2513 imethod = (MonoMethodInflated *) inflated;
2515 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2516 token = method_encode_methodspec (assembly, inflated);
2518 guint32 sig = method_encode_signature (
2519 assembly, mono_method_signature (imethod->declaring));
2520 token = mono_image_get_memberref_token (
2521 assembly, &inflated->klass->byval_arg, inflated->name, sig);
2524 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2529 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2531 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2534 m = mono_get_inflated_method (m);
2536 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2537 token = mono_image_get_memberref_token (
2538 assembly, &m->klass->byval_arg, m->name, sig);
2544 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2546 MonoDynamicTable *table;
2553 char *b = blob_size;
2557 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2558 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2559 * Because of this, we must not insert it into the `typeref' hash table.
2562 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2566 g_assert (tb->generic_params);
2567 klass = mono_class_from_mono_type (tb->type.type);
2569 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2570 encode_type (assembly, &klass->byval_arg, p, &p);
2572 count = mono_array_length (tb->generic_params);
2573 mono_metadata_encode_value (count, p, &p);
2574 for (i = 0; i < count; i++) {
2575 MonoReflectionGenericParam *gparam;
2577 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2579 encode_type (assembly, gparam->type.type, p, &p);
2582 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2583 g_assert (p-sig < 128);
2585 if (assembly->save) {
2586 mono_metadata_encode_value (p-sig, b, &b);
2587 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2588 alloc_table (table, table->rows + 1);
2589 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2590 values [MONO_TYPESPEC_SIGNATURE] = token;
2593 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2594 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2600 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2602 MonoDynamicTable *table;
2605 guint32 token, pclass, parent, sig;
2608 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2612 klass = mono_class_from_mono_type (fb->typeb->type);
2613 name = mono_string_to_utf8 (fb->name);
2615 sig = fieldref_encode_signature (assembly, fb->type->type);
2617 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2618 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2620 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2621 parent >>= MONO_TYPEDEFORREF_BITS;
2623 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2625 if (assembly->save) {
2626 alloc_table (table, table->rows + 1);
2627 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2628 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2629 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2630 values [MONO_MEMBERREF_SIGNATURE] = sig;
2633 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2635 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2640 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2648 char *b = blob_size;
2650 if (!assembly->save)
2654 g_assert (helper->type == 2);
2656 if (helper->arguments)
2657 nargs = mono_array_length (helper->arguments);
2661 size = 10 + (nargs * 10);
2663 p = buf = g_malloc (size);
2665 /* Encode calling convention */
2666 /* Change Any to Standard */
2667 if ((helper->call_conv & 0x03) == 0x03)
2668 helper->call_conv = 0x01;
2669 /* explicit_this implies has_this */
2670 if (helper->call_conv & 0x40)
2671 helper->call_conv &= 0x20;
2673 if (helper->call_conv == 0) { /* Unmanaged */
2674 *p = helper->unmanaged_call_conv - 1;
2677 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2678 if (helper->call_conv & 0x02) /* varargs */
2683 mono_metadata_encode_value (nargs, p, &p);
2684 encode_reflection_type (assembly, helper->return_type, p, &p);
2685 for (i = 0; i < nargs; ++i) {
2686 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2687 encode_reflection_type (assembly, pt, p, &p);
2690 g_assert (p - buf < size);
2691 mono_metadata_encode_value (p-buf, b, &b);
2692 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2699 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2702 MonoDynamicTable *table;
2705 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2706 idx = table->next_idx ++;
2708 alloc_table (table, table->rows);
2709 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2711 values [MONO_STAND_ALONE_SIGNATURE] =
2712 mono_reflection_encode_sighelper (assembly, helper);
2718 reflection_cc_to_file (int call_conv) {
2719 switch (call_conv & 0x3) {
2721 case 1: return MONO_CALL_DEFAULT;
2722 case 2: return MONO_CALL_VARARG;
2724 g_assert_not_reached ();
2731 MonoMethodSignature *sig;
2737 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2742 MonoMethodSignature *sig;
2745 name = mono_string_to_utf8 (m->name);
2746 nparams = mono_array_length (m->parameters);
2747 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2749 sig->sentinelpos = -1;
2750 sig->call_convention = reflection_cc_to_file (m->call_conv);
2751 sig->param_count = nparams;
2752 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2753 for (i = 0; i < nparams; ++i) {
2754 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2755 sig->params [i] = t->type;
2758 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2760 if (strcmp (name, am->name) == 0 &&
2761 mono_metadata_type_equal (am->parent, m->parent->type) &&
2762 mono_metadata_signature_equal (am->sig, sig)) {
2765 m->table_idx = am->token & 0xffffff;
2769 am = g_new0 (ArrayMethod, 1);
2772 am->parent = m->parent->type;
2773 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2774 method_encode_signature (assembly, sig));
2775 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2776 m->table_idx = am->token & 0xffffff;
2781 * Insert into the metadata tables all the info about the TypeBuilder tb.
2782 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2785 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2787 MonoDynamicTable *table;
2789 int i, is_object = 0, is_system = 0;
2792 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2793 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2794 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2795 n = mono_string_to_utf8 (tb->name);
2796 if (strcmp (n, "Object") == 0)
2798 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2800 n = mono_string_to_utf8 (tb->nspace);
2801 if (strcmp (n, "System") == 0)
2803 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2805 if (tb->parent && !(is_system && is_object) &&
2806 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2807 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2809 values [MONO_TYPEDEF_EXTENDS] = 0;
2811 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2812 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2815 * if we have explicitlayout or sequentiallayouts, output data in the
2816 * ClassLayout table.
2818 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2819 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2820 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2822 alloc_table (table, table->rows);
2823 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2824 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2825 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2826 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2829 /* handle interfaces */
2830 if (tb->interfaces) {
2831 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2833 table->rows += mono_array_length (tb->interfaces);
2834 alloc_table (table, table->rows);
2835 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2836 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2837 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2838 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2839 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2840 values += MONO_INTERFACEIMPL_SIZE;
2846 table = &assembly->tables [MONO_TABLE_FIELD];
2847 table->rows += tb->num_fields;
2848 alloc_table (table, table->rows);
2849 for (i = 0; i < tb->num_fields; ++i)
2850 mono_image_get_field_info (
2851 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2854 /* handle constructors */
2856 table = &assembly->tables [MONO_TABLE_METHOD];
2857 table->rows += mono_array_length (tb->ctors);
2858 alloc_table (table, table->rows);
2859 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2860 mono_image_get_ctor_info (domain,
2861 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2864 /* handle methods */
2866 table = &assembly->tables [MONO_TABLE_METHOD];
2867 table->rows += tb->num_methods;
2868 alloc_table (table, table->rows);
2869 for (i = 0; i < tb->num_methods; ++i)
2870 mono_image_get_method_info (
2871 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2874 /* Do the same with properties etc.. */
2875 if (tb->events && mono_array_length (tb->events)) {
2876 table = &assembly->tables [MONO_TABLE_EVENT];
2877 table->rows += mono_array_length (tb->events);
2878 alloc_table (table, table->rows);
2879 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2881 alloc_table (table, table->rows);
2882 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2883 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2884 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2885 for (i = 0; i < mono_array_length (tb->events); ++i)
2886 mono_image_get_event_info (
2887 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2889 if (tb->properties && mono_array_length (tb->properties)) {
2890 table = &assembly->tables [MONO_TABLE_PROPERTY];
2891 table->rows += mono_array_length (tb->properties);
2892 alloc_table (table, table->rows);
2893 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2895 alloc_table (table, table->rows);
2896 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2897 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2898 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2899 for (i = 0; i < mono_array_length (tb->properties); ++i)
2900 mono_image_get_property_info (
2901 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2904 /* handle generic parameters */
2905 if (tb->generic_params) {
2906 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2907 table->rows += mono_array_length (tb->generic_params);
2908 alloc_table (table, table->rows);
2909 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2910 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2912 mono_image_get_generic_param_info (
2913 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2917 mono_image_add_decl_security (assembly,
2918 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2921 MonoDynamicTable *ntable;
2923 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2924 ntable->rows += mono_array_length (tb->subtypes);
2925 alloc_table (ntable, ntable->rows);
2926 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2928 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2929 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2931 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2932 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2933 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2934 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2935 mono_string_to_utf8 (tb->name), tb->table_idx,
2936 ntable->next_idx, ntable->rows);*/
2937 values += MONO_NESTED_CLASS_SIZE;
2944 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2948 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2950 if (!type->subtypes)
2953 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2954 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2955 collect_types (types, subtype);
2960 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2962 if ((*type1)->table_idx < (*type2)->table_idx)
2965 if ((*type1)->table_idx > (*type2)->table_idx)
2972 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2977 for (i = 0; i < mono_array_length (pinfo); ++i) {
2978 MonoReflectionParamBuilder *pb;
2979 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2982 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2987 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2990 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2992 for (i = 0; i < tb->num_fields; ++i) {
2993 MonoReflectionFieldBuilder* fb;
2994 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2995 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2999 for (i = 0; i < mono_array_length (tb->events); ++i) {
3000 MonoReflectionEventBuilder* eb;
3001 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3002 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3005 if (tb->properties) {
3006 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3007 MonoReflectionPropertyBuilder* pb;
3008 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3009 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3013 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3014 MonoReflectionCtorBuilder* cb;
3015 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3016 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3017 params_add_cattrs (assembly, cb->pinfo);
3022 for (i = 0; i < tb->num_methods; ++i) {
3023 MonoReflectionMethodBuilder* mb;
3024 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3025 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3026 params_add_cattrs (assembly, mb->pinfo);
3031 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3032 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3037 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3041 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3043 if (moduleb->global_methods) {
3044 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3045 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3046 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3047 params_add_cattrs (assembly, mb->pinfo);
3051 if (moduleb->global_fields) {
3052 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3053 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3054 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3058 if (moduleb->types) {
3059 for (i = 0; i < moduleb->num_types; ++i)
3060 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3065 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3067 MonoDynamicTable *table;
3071 char *b = blob_size;
3074 table = &assembly->tables [MONO_TABLE_FILE];
3076 alloc_table (table, table->rows);
3077 values = table->values + table->next_idx * MONO_FILE_SIZE;
3078 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3079 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3080 if (module->image->dynamic) {
3081 /* This depends on the fact that the main module is emitted last */
3082 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3083 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3086 path = g_strdup (module->image->name);
3088 mono_sha1_get_digest_from_file (path, hash);
3091 mono_metadata_encode_value (20, b, &b);
3092 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3093 mono_image_add_stream_data (&assembly->blob, hash, 20);
3098 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3100 MonoDynamicTable *table;
3104 table = &assembly->tables [MONO_TABLE_MODULE];
3105 mb->table_idx = table->next_idx ++;
3106 name = mono_string_to_utf8 (mb->module.name);
3107 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3109 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3112 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3113 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3114 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3115 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3119 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3120 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3122 MonoDynamicTable *table;
3126 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3127 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3130 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3132 alloc_table (table, table->rows);
3133 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3135 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3136 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3137 if (klass->nested_in)
3138 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3140 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3141 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3142 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3144 res = table->next_idx;
3148 /* Emit nested types */
3149 if (klass->nested_classes) {
3152 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3153 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3160 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3161 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3166 klass = mono_class_from_mono_type (tb->type.type);
3168 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3170 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3171 parent_index, assembly);
3175 * We need to do this ourselves since klass->nested_classes is not set up.
3178 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3179 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3184 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3185 guint32 module_index, MonoDynamicImage *assembly)
3187 MonoImage *image = module->image;
3191 t = &image->tables [MONO_TABLE_TYPEDEF];
3193 for (i = 0; i < t->rows; ++i) {
3194 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3196 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3197 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3202 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3204 MonoDynamicTable *table;
3210 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3212 if (assemblyb->type_forwarders) {
3213 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3214 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3220 klass = mono_class_from_mono_type (t->type);
3222 scope = resolution_scope_from_image (assembly, klass->image);
3223 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3224 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3227 alloc_table (table, table->rows);
3228 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3230 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3231 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3232 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3233 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3234 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3239 #define align_pointer(base,p)\
3241 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3243 (p) += 4 - (__diff & 3);\
3247 compare_constants (const void *a, const void *b)
3249 const guint32 *a_values = a;
3250 const guint32 *b_values = b;
3251 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3255 compare_semantics (const void *a, const void *b)
3257 const guint32 *a_values = a;
3258 const guint32 *b_values = b;
3259 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3262 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3266 compare_custom_attrs (const void *a, const void *b)
3268 const guint32 *a_values = a;
3269 const guint32 *b_values = b;
3271 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3275 compare_field_marshal (const void *a, const void *b)
3277 const guint32 *a_values = a;
3278 const guint32 *b_values = b;
3280 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3284 compare_nested (const void *a, const void *b)
3286 const guint32 *a_values = a;
3287 const guint32 *b_values = b;
3289 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3293 compare_genericparam (const void *a, const void *b)
3295 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3296 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3298 if ((*b_entry)->owner == (*a_entry)->owner)
3300 (*a_entry)->gparam->type.type->data.generic_param->num -
3301 (*b_entry)->gparam->type.type->data.generic_param->num;
3303 return (*a_entry)->owner - (*b_entry)->owner;
3307 compare_declsecurity_attrs (const void *a, const void *b)
3309 const guint32 *a_values = a;
3310 const guint32 *b_values = b;
3312 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3316 pad_heap (MonoDynamicStream *sh)
3318 if (sh->index & 3) {
3319 int sz = 4 - (sh->index & 3);
3320 memset (sh->data + sh->index, 0, sz);
3327 MonoDynamicStream *stream;
3331 * build_compressed_metadata() fills in the blob of data that represents the
3332 * raw metadata as it will be saved in the PE file. The five streams are output
3333 * and the metadata tables are comnpressed from the guint32 array representation,
3334 * to the compressed on-disk format.
3337 build_compressed_metadata (MonoDynamicImage *assembly)
3339 MonoDynamicTable *table;
3341 guint64 valid_mask = 0;
3342 guint64 sorted_mask;
3343 guint32 heapt_size = 0;
3344 guint32 meta_size = 256; /* allow for header and other stuff */
3345 guint32 table_offset;
3346 guint32 ntables = 0;
3352 struct StreamDesc stream_desc [5];
3354 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3355 for (i = 0; i < assembly->gen_params->len; i++){
3356 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3357 write_generic_param_entry (assembly, entry);
3360 stream_desc [0].name = "#~";
3361 stream_desc [0].stream = &assembly->tstream;
3362 stream_desc [1].name = "#Strings";
3363 stream_desc [1].stream = &assembly->sheap;
3364 stream_desc [2].name = "#US";
3365 stream_desc [2].stream = &assembly->us;
3366 stream_desc [3].name = "#Blob";
3367 stream_desc [3].stream = &assembly->blob;
3368 stream_desc [4].name = "#GUID";
3369 stream_desc [4].stream = &assembly->guid;
3371 /* tables that are sorted */
3372 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3373 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3374 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3375 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3376 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3377 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3379 /* Compute table sizes */
3380 /* the MonoImage has already been created in mono_image_basic_init() */
3381 meta = &assembly->image;
3383 /* sizes should be multiple of 4 */
3384 pad_heap (&assembly->blob);
3385 pad_heap (&assembly->guid);
3386 pad_heap (&assembly->sheap);
3387 pad_heap (&assembly->us);
3389 /* Setup the info used by compute_sizes () */
3390 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3391 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3392 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3394 meta_size += assembly->blob.index;
3395 meta_size += assembly->guid.index;
3396 meta_size += assembly->sheap.index;
3397 meta_size += assembly->us.index;
3399 for (i=0; i < MONO_TABLE_NUM; ++i)
3400 meta->tables [i].rows = assembly->tables [i].rows;
3402 for (i = 0; i < MONO_TABLE_NUM; i++){
3403 if (meta->tables [i].rows == 0)
3405 valid_mask |= (guint64)1 << i;
3407 meta->tables [i].row_size = mono_metadata_compute_size (
3408 meta, i, &meta->tables [i].size_bitfield);
3409 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3411 heapt_size += 24; /* #~ header size */
3412 heapt_size += ntables * 4;
3413 /* make multiple of 4 */
3416 meta_size += heapt_size;
3417 meta->raw_metadata = g_malloc0 (meta_size);
3418 p = meta->raw_metadata;
3419 /* the metadata signature */
3420 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3421 /* version numbers and 4 bytes reserved */
3422 int16val = (guint16*)p;
3423 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3424 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3426 /* version string */
3427 int32val = (guint32*)p;
3428 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3430 memcpy (p, meta->version, strlen (meta->version));
3431 p += GUINT32_FROM_LE (*int32val);
3432 align_pointer (meta->raw_metadata, p);
3433 int16val = (guint16*)p;
3434 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3435 *int16val = GUINT16_TO_LE (5); /* number of streams */
3439 * write the stream info.
3441 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3442 table_offset += 3; table_offset &= ~3;
3444 assembly->tstream.index = heapt_size;
3445 for (i = 0; i < 5; ++i) {
3446 int32val = (guint32*)p;
3447 stream_desc [i].stream->offset = table_offset;
3448 *int32val++ = GUINT32_TO_LE (table_offset);
3449 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3450 table_offset += GUINT32_FROM_LE (*int32val);
3451 table_offset += 3; table_offset &= ~3;
3453 strcpy (p, stream_desc [i].name);
3454 p += strlen (stream_desc [i].name) + 1;
3455 align_pointer (meta->raw_metadata, p);
3458 * now copy the data, the table stream header and contents goes first.
3460 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3461 p = meta->raw_metadata + assembly->tstream.offset;
3462 int32val = (guint32*)p;
3463 *int32val = GUINT32_TO_LE (0); /* reserved */
3466 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3467 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3468 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3469 *p++ = 2; /* version */
3472 *p++ = 1; /* version */
3476 if (meta->idx_string_wide)
3478 if (meta->idx_guid_wide)
3480 if (meta->idx_blob_wide)
3483 *p++ = 1; /* reserved */
3484 int64val = (guint64*)p;
3485 *int64val++ = GUINT64_TO_LE (valid_mask);
3486 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3488 int32val = (guint32*)p;
3489 for (i = 0; i < MONO_TABLE_NUM; i++){
3490 if (meta->tables [i].rows == 0)
3492 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3494 p = (unsigned char*)int32val;
3496 /* sort the tables that still need sorting */
3497 table = &assembly->tables [MONO_TABLE_CONSTANT];
3499 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3500 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3502 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3503 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3505 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3506 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3508 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3509 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3511 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3512 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3513 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3515 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3517 /* compress the tables */
3518 for (i = 0; i < MONO_TABLE_NUM; i++){
3521 guint32 bitfield = meta->tables [i].size_bitfield;
3522 if (!meta->tables [i].rows)
3524 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3525 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3526 meta->tables [i].base = p;
3527 for (row = 1; row <= meta->tables [i].rows; ++row) {
3528 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3529 for (col = 0; col < assembly->tables [i].columns; ++col) {
3530 switch (mono_metadata_table_size (bitfield, col)) {
3532 *p++ = values [col];
3535 *p++ = values [col] & 0xff;
3536 *p++ = (values [col] >> 8) & 0xff;
3539 *p++ = values [col] & 0xff;
3540 *p++ = (values [col] >> 8) & 0xff;
3541 *p++ = (values [col] >> 16) & 0xff;
3542 *p++ = (values [col] >> 24) & 0xff;
3545 g_assert_not_reached ();
3549 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3552 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3553 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3554 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3555 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3556 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3558 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3562 * Some tables in metadata need to be sorted according to some criteria, but
3563 * when methods and fields are first created with reflection, they may be assigned a token
3564 * that doesn't correspond to the final token they will get assigned after the sorting.
3565 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3566 * with the reflection objects that represent them. Once all the tables are set up, the
3567 * reflection objects will contains the correct table index. fixup_method() will fixup the
3568 * tokens for the method with ILGenerator @ilgen.
3571 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3572 guint32 code_idx = GPOINTER_TO_UINT (value);
3573 MonoReflectionILTokenInfo *iltoken;
3574 MonoReflectionFieldBuilder *field;
3575 MonoReflectionCtorBuilder *ctor;
3576 MonoReflectionMethodBuilder *method;
3577 MonoReflectionTypeBuilder *tb;
3578 MonoReflectionArrayMethod *am;
3580 unsigned char *target;
3582 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3583 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3584 target = assembly->code.data + code_idx + iltoken->code_pos;
3585 switch (target [3]) {
3586 case MONO_TABLE_FIELD:
3587 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3588 field = (MonoReflectionFieldBuilder *)iltoken->member;
3589 idx = field->table_idx;
3590 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3591 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3592 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3594 g_assert_not_reached ();
3597 case MONO_TABLE_METHOD:
3598 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3599 method = (MonoReflectionMethodBuilder *)iltoken->member;
3600 idx = method->table_idx;
3601 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3602 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3603 idx = ctor->table_idx;
3604 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3605 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3606 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3607 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3609 g_assert_not_reached ();
3612 case MONO_TABLE_TYPEDEF:
3613 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3614 g_assert_not_reached ();
3615 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3616 idx = tb->table_idx;
3618 case MONO_TABLE_MEMBERREF:
3619 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3620 am = (MonoReflectionArrayMethod*)iltoken->member;
3621 idx = am->table_idx;
3622 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3623 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3624 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3625 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3626 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3627 g_assert (m->klass->generic_class || m->klass->generic_container);
3629 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3631 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3632 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3633 g_assert (f->generic_info);
3635 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3638 g_assert_not_reached ();
3641 case MONO_TABLE_METHODSPEC:
3642 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3643 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3644 g_assert (mono_method_signature (m)->generic_param_count);
3647 g_assert_not_reached ();
3651 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3653 target [0] = idx & 0xff;
3654 target [1] = (idx >> 8) & 0xff;
3655 target [2] = (idx >> 16) & 0xff;
3662 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3663 * value is not known when the table is emitted.
3666 fixup_cattrs (MonoDynamicImage *assembly)
3668 MonoDynamicTable *table;
3670 guint32 type, i, idx, token;
3673 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3675 for (i = 0; i < table->rows; ++i) {
3676 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3678 type = values [MONO_CUSTOM_ATTR_TYPE];
3679 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3680 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3681 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3682 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3685 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3686 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3687 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3688 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3697 * The METHODIMPL table might contain METHODDEF tokens whose final
3698 * value is not known when the table is emitted.
3701 fixup_methodimpl (MonoDynamicImage *assembly)
3703 MonoDynamicTable *table;
3705 guint32 decl, i, idx, token;
3708 table = &assembly->tables [MONO_TABLE_METHODIMPL];
3710 for (i = 0; i < table->rows; ++i) {
3711 values = table->values + ((i + 1) * MONO_METHODIMPL_SIZE);
3712 decl = values [MONO_METHODIMPL_DECLARATION];
3714 idx = decl >> MONO_METHODDEFORREF_BITS;
3715 if ((decl & MONO_METHODDEFORREF_MASK) != MONO_METHODDEFORREF_METHODDEF)
3718 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3719 method = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3722 if (!strcmp (method->vtable->klass->name, "MethodBuilder")) {
3723 token = mono_image_create_token (assembly, method, FALSE);
3724 idx = mono_metadata_token_index (token);
3725 values [MONO_METHODIMPL_DECLARATION] = (idx << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3731 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3733 MonoDynamicTable *table;
3737 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3739 alloc_table (table, table->rows);
3740 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3741 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3742 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3743 name = mono_string_to_utf8 (rsrc->name);
3744 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3746 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3751 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3753 MonoDynamicTable *table;
3757 char *b = blob_size;
3759 guint32 idx, offset;
3761 if (rsrc->filename) {
3762 name = mono_string_to_utf8 (rsrc->filename);
3763 sname = g_path_get_basename (name);
3765 table = &assembly->tables [MONO_TABLE_FILE];
3767 alloc_table (table, table->rows);
3768 values = table->values + table->next_idx * MONO_FILE_SIZE;
3769 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3770 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3773 mono_sha1_get_digest_from_file (name, hash);
3774 mono_metadata_encode_value (20, b, &b);
3775 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3776 mono_image_add_stream_data (&assembly->blob, hash, 20);
3778 idx = table->next_idx++;
3780 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3783 offset = mono_array_length (rsrc->data);
3784 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3785 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3786 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3787 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3791 * The entry should be emitted into the MANIFESTRESOURCE table of
3792 * the main module, but that needs to reference the FILE table
3793 * which isn't emitted yet.
3800 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3804 set_version_from_string (MonoString *version, guint32 *values)
3806 gchar *ver, *p, *str;
3809 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3810 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3811 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3812 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3815 ver = str = mono_string_to_utf8 (version);
3816 for (i = 0; i < 4; ++i) {
3817 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3823 /* handle Revision and Build */
3833 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3837 char *b = blob_size;
3842 len = mono_array_length (pkey);
3843 mono_metadata_encode_value (len, b, &b);
3844 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3845 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3847 /* Special case: check for ECMA key (16 bytes) */
3848 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, guint8, 0), len)) {
3849 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3850 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3851 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3852 /* minimum key size (in 2.0) is 384 bits */
3853 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3855 /* FIXME - verifier */
3856 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3857 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3859 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3865 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3867 MonoDynamicTable *table;
3868 MonoDynamicImage *assembly;
3869 MonoReflectionAssemblyBuilder *assemblyb;
3874 guint32 module_index;
3876 assemblyb = moduleb->assemblyb;
3877 assembly = moduleb->dynamic_image;
3878 domain = mono_object_domain (assemblyb);
3880 /* Emit ASSEMBLY table */
3881 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3882 alloc_table (table, 1);
3883 values = table->values + MONO_ASSEMBLY_SIZE;
3884 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3885 name = mono_string_to_utf8 (assemblyb->name);
3886 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3888 if (assemblyb->culture) {
3889 name = mono_string_to_utf8 (assemblyb->culture);
3890 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3893 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3895 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3896 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3897 set_version_from_string (assemblyb->version, values);
3899 /* Emit FILE + EXPORTED_TYPE table */
3901 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3903 MonoReflectionModuleBuilder *file_module =
3904 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3905 if (file_module != moduleb) {
3906 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3908 if (file_module->types) {
3909 for (j = 0; j < file_module->num_types; ++j) {
3910 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3911 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3916 if (assemblyb->loaded_modules) {
3917 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3918 MonoReflectionModule *file_module =
3919 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3920 mono_image_fill_file_table (domain, file_module, assembly);
3922 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3925 if (assemblyb->type_forwarders)
3926 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3928 /* Emit MANIFESTRESOURCE table */
3930 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3932 MonoReflectionModuleBuilder *file_module =
3933 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3934 /* The table for the main module is emitted later */
3935 if (file_module != moduleb) {
3937 if (file_module->resources) {
3938 int len = mono_array_length (file_module->resources);
3939 for (j = 0; j < len; ++j) {
3940 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3941 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3949 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3950 * for the modulebuilder @moduleb.
3951 * At the end of the process, method and field tokens are fixed up and the
3952 * on-disk compressed metadata representation is created.
3955 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3957 MonoDynamicTable *table;
3958 MonoDynamicImage *assembly;
3959 MonoReflectionAssemblyBuilder *assemblyb;
3964 assemblyb = moduleb->assemblyb;
3965 assembly = moduleb->dynamic_image;
3966 domain = mono_object_domain (assemblyb);
3968 if (assembly->text_rva)
3971 assembly->text_rva = START_TEXT_RVA;
3973 if (moduleb->is_main) {
3974 mono_image_emit_manifest (moduleb);
3977 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3978 table->rows = 1; /* .<Module> */
3980 alloc_table (table, table->rows);
3982 * Set the first entry.
3984 values = table->values + table->columns;
3985 values [MONO_TYPEDEF_FLAGS] = 0;
3986 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3987 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3988 values [MONO_TYPEDEF_EXTENDS] = 0;
3989 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3990 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3993 * handle global methods
3994 * FIXME: test what to do when global methods are defined in multiple modules.
3996 if (moduleb->global_methods) {
3997 table = &assembly->tables [MONO_TABLE_METHOD];
3998 table->rows += mono_array_length (moduleb->global_methods);
3999 alloc_table (table, table->rows);
4000 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4001 mono_image_get_method_info (
4002 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4004 if (moduleb->global_fields) {
4005 table = &assembly->tables [MONO_TABLE_FIELD];
4006 table->rows += mono_array_length (moduleb->global_fields);
4007 alloc_table (table, table->rows);
4008 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4009 mono_image_get_field_info (
4010 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4013 table = &assembly->tables [MONO_TABLE_MODULE];
4014 alloc_table (table, 1);
4015 mono_image_fill_module_table (domain, moduleb, assembly);
4019 /* Collect all types into a list sorted by their table_idx */
4020 GPtrArray *types = g_ptr_array_new ();
4023 for (i = 0; i < moduleb->num_types; ++i) {
4024 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4025 collect_types (types, type);
4028 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4029 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4030 table->rows += types->len;
4031 alloc_table (table, table->rows);
4034 * Emit type names + namespaces at one place inside the string heap,
4035 * so load_class_names () needs to touch fewer pages.
4037 for (i = 0; i < types->len; ++i) {
4038 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4041 n = mono_string_to_utf8 (tb->nspace);
4042 string_heap_insert (&assembly->sheap, n);
4045 for (i = 0; i < types->len; ++i) {
4046 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4049 n = mono_string_to_utf8 (tb->name);
4050 string_heap_insert (&assembly->sheap, n);
4054 for (i = 0; i < types->len; ++i) {
4055 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4056 mono_image_get_type_info (domain, type, assembly);
4058 g_ptr_array_free (types, TRUE);
4062 * table->rows is already set above and in mono_image_fill_module_table.
4064 /* add all the custom attributes at the end, once all the indexes are stable */
4065 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4067 /* CAS assembly permissions */
4068 if (assemblyb->permissions_minimum)
4069 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4070 if (assemblyb->permissions_optional)
4071 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4072 if (assemblyb->permissions_refused)
4073 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4075 module_add_cattrs (assembly, moduleb);
4078 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4079 fixup_cattrs (assembly);
4080 fixup_methodimpl (assembly);
4084 * mono_image_insert_string:
4085 * @module: module builder object
4088 * Insert @str into the user string stream of @module.
4091 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4093 MonoDynamicImage *assembly;
4098 MONO_ARCH_SAVE_REGS;
4100 if (!module->dynamic_image)
4101 mono_image_module_basic_init (module);
4103 assembly = module->dynamic_image;
4105 if (assembly->save) {
4106 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4107 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4108 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4110 char *swapped = g_malloc (2 * mono_string_length (str));
4111 const char *p = (const char*)mono_string_chars (str);
4113 swap_with_size (swapped, p, 2, mono_string_length (str));
4114 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4118 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4120 mono_image_add_stream_data (&assembly->us, "", 1);
4122 idx = assembly->us.index ++;
4125 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4127 return MONO_TOKEN_STRING | idx;
4131 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4136 klass = obj->vtable->klass;
4137 if (strcmp (klass->name, "MonoMethod") == 0) {
4138 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4139 MonoMethodSignature *sig, *old;
4140 guint32 sig_token, parent;
4143 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4145 nargs = mono_array_length (opt_param_types);
4146 old = mono_method_signature (method);
4147 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4149 sig->hasthis = old->hasthis;
4150 sig->explicit_this = old->explicit_this;
4151 sig->call_convention = old->call_convention;
4152 sig->generic_param_count = old->generic_param_count;
4153 sig->param_count = old->param_count + nargs;
4154 sig->sentinelpos = old->param_count;
4155 sig->ret = old->ret;
4157 for (i = 0; i < old->param_count; i++)
4158 sig->params [i] = old->params [i];
4160 for (i = 0; i < nargs; i++) {
4161 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4162 sig->params [old->param_count + i] = rt->type;
4165 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4166 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4167 parent >>= MONO_TYPEDEFORREF_BITS;
4169 parent <<= MONO_MEMBERREF_PARENT_BITS;
4170 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4172 sig_token = method_encode_signature (assembly, sig);
4173 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4174 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4175 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4176 ReflectionMethodBuilder rmb;
4177 guint32 parent, sig;
4179 reflection_methodbuilder_from_method_builder (&rmb, mb);
4180 rmb.opt_types = opt_param_types;
4182 sig = method_builder_encode_signature (assembly, &rmb);
4184 parent = mono_image_create_token (assembly, obj, TRUE);
4185 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4187 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4188 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4190 token = mono_image_get_varargs_method_token (
4191 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4193 g_error ("requested method token for %s\n", klass->name);
4200 * mono_image_create_token:
4201 * @assembly: a dynamic assembly
4204 * Get a token to insert in the IL code stream for the given MemberInfo.
4205 * @obj can be one of:
4206 * ConstructorBuilder
4216 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4221 klass = obj->vtable->klass;
4222 if (strcmp (klass->name, "MethodBuilder") == 0) {
4223 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4225 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4226 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4228 token = mono_image_get_methodbuilder_token (assembly, mb);
4229 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4230 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4231 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4233 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4234 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4236 token = mono_image_get_ctorbuilder_token (assembly, mb);
4237 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4238 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4239 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4240 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4241 if (tb->generic_params) {
4242 token = mono_image_get_generic_field_token (assembly, fb);
4244 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4246 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4247 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4248 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4249 } else if (strcmp (klass->name, "MonoType") == 0 ||
4250 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4251 MonoReflectionType *tb = (MonoReflectionType *)obj;
4252 token = mono_metadata_token_from_dor (
4253 mono_image_typedef_or_ref (assembly, tb->type));
4254 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4255 MonoReflectionType *tb = (MonoReflectionType *)obj;
4256 token = mono_metadata_token_from_dor (
4257 mono_image_typedef_or_ref (assembly, tb->type));
4258 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4259 strcmp (klass->name, "MonoMethod") == 0 ||
4260 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4261 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4262 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4263 if (m->method->is_inflated) {
4264 if (create_methodspec)
4265 token = mono_image_get_methodspec_token (assembly, m->method);
4267 token = mono_image_get_inflated_method_token (assembly, m->method);
4268 } else if ((m->method->klass->image == &assembly->image) &&
4269 !m->method->klass->generic_class) {
4270 static guint32 method_table_idx = 0xffffff;
4271 if (m->method->klass->wastypebuilder) {
4272 /* we use the same token as the one that was assigned
4273 * to the Methodbuilder.
4274 * FIXME: do the equivalent for Fields.
4276 token = m->method->token;
4279 * Each token should have a unique index, but the indexes are
4280 * assigned by managed code, so we don't know about them. An
4281 * easy solution is to count backwards...
4283 method_table_idx --;
4284 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4287 token = mono_image_get_methodref_token (assembly, m->method);
4289 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4290 } else if (strcmp (klass->name, "MonoField") == 0) {
4291 MonoReflectionField *f = (MonoReflectionField *)obj;
4292 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4293 static guint32 field_table_idx = 0xffffff;
4295 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4297 token = mono_image_get_fieldref_token (assembly, f);
4299 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4300 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4301 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4302 token = mono_image_get_array_token (assembly, m);
4303 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4304 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4305 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4307 g_error ("requested token for %s\n", klass->name);
4310 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4316 guint32 import_lookup_table;
4320 guint32 import_address_table_rva;
4328 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4330 static MonoDynamicImage*
4331 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4333 static const guchar entrycode [16] = {0xff, 0x25, 0};
4334 MonoDynamicImage *image;
4337 const char *version = mono_get_runtime_info ()->runtime_version;
4340 image = GC_MALLOC (sizeof (MonoDynamicImage));
4342 image = g_new0 (MonoDynamicImage, 1);
4345 /*g_print ("created image %p\n", image);*/
4346 /* keep in sync with image.c */
4347 image->image.name = assembly_name;
4348 image->image.assembly_name = image->image.name; /* they may be different */
4349 image->image.module_name = module_name;
4350 image->image.version = g_strdup (version);
4351 image->image.md_version_major = 1;
4352 image->image.md_version_minor = 1;
4353 image->image.dynamic = TRUE;
4355 image->image.references = g_new0 (MonoAssembly*, 1);
4356 image->image.references [0] = NULL;
4358 mono_image_init (&image->image);
4360 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4361 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4362 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4363 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4364 image->handleref = g_hash_table_new (NULL, NULL);
4365 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4366 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4367 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4368 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4369 image->gen_params = g_ptr_array_new ();
4371 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4372 string_heap_init (&image->sheap);
4373 mono_image_add_stream_data (&image->us, "", 1);
4374 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4375 /* import tables... */
4376 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4377 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4378 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4379 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4380 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4381 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4382 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4383 stream_data_align (&image->code);
4385 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4387 for (i=0; i < MONO_TABLE_NUM; ++i) {
4388 image->tables [i].next_idx = 1;
4389 image->tables [i].columns = table_sizes [i];
4392 image->image.assembly = (MonoAssembly*)assembly;
4393 image->run = assembly->run;
4394 image->save = assembly->save;
4395 image->pe_kind = 0x1; /* ILOnly */
4396 image->machine = 0x14c; /* I386 */
4402 * mono_image_basic_init:
4403 * @assembly: an assembly builder object
4405 * Create the MonoImage that represents the assembly builder and setup some
4406 * of the helper hash table and the basic metadata streams.
4409 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4411 MonoDynamicAssembly *assembly;
4412 MonoDynamicImage *image;
4413 MonoDomain *domain = mono_object_domain (assemblyb);
4415 MONO_ARCH_SAVE_REGS;
4417 if (assemblyb->dynamic_assembly)
4421 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4423 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4426 assembly->assembly.ref_count = 1;
4427 assembly->assembly.dynamic = TRUE;
4428 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4429 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4430 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4431 if (assemblyb->culture)
4432 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4434 assembly->assembly.aname.culture = g_strdup ("");
4436 if (assemblyb->version) {
4437 char *vstr = mono_string_to_utf8 (assemblyb->version);
4438 char **version = g_strsplit (vstr, ".", 4);
4439 char **parts = version;
4440 assembly->assembly.aname.major = atoi (*parts++);
4441 assembly->assembly.aname.minor = atoi (*parts++);
4442 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4443 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4445 g_strfreev (version);
4448 assembly->assembly.aname.major = 0;
4449 assembly->assembly.aname.minor = 0;
4450 assembly->assembly.aname.build = 0;
4451 assembly->assembly.aname.revision = 0;
4454 assembly->run = assemblyb->access != 2;
4455 assembly->save = assemblyb->access != 1;
4457 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4458 image->initial_image = TRUE;
4459 assembly->assembly.aname.name = image->image.name;
4460 assembly->assembly.image = &image->image;
4462 mono_domain_assemblies_lock (domain);
4463 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4464 mono_domain_assemblies_unlock (domain);
4466 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4467 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4471 calc_section_size (MonoDynamicImage *assembly)
4475 /* alignment constraints */
4476 assembly->code.index += 3;
4477 assembly->code.index &= ~3;
4478 assembly->meta_size += 3;
4479 assembly->meta_size &= ~3;
4480 assembly->resources.index += 3;
4481 assembly->resources.index &= ~3;
4483 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4484 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4487 if (assembly->win32_res) {
4488 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4490 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4491 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4495 assembly->sections [MONO_SECTION_RELOC].size = 12;
4496 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4506 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4510 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4512 ResTreeNode *t1 = (ResTreeNode*)a;
4513 ResTreeNode *t2 = (ResTreeNode*)b;
4515 return t1->id - t2->id;
4519 * resource_tree_create:
4521 * Organize the resources into a resource tree.
4523 static ResTreeNode *
4524 resource_tree_create (MonoArray *win32_resources)
4526 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4530 tree = g_new0 (ResTreeNode, 1);
4532 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4533 MonoReflectionWin32Resource *win32_res =
4534 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4538 /* FIXME: BUG: this stores managed references in unmanaged memory */
4539 lang_node = g_new0 (ResTreeNode, 1);
4540 lang_node->id = win32_res->lang_id;
4541 lang_node->win32_res = win32_res;
4543 /* Create type node if neccesary */
4545 for (l = tree->children; l; l = l->next)
4546 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4547 type_node = (ResTreeNode*)l->data;
4552 type_node = g_new0 (ResTreeNode, 1);
4553 type_node->id = win32_res->res_type;
4556 * The resource types have to be sorted otherwise
4557 * Windows Explorer can't display the version information.
4559 tree->children = g_slist_insert_sorted (tree->children,
4560 type_node, resource_tree_compare_by_id);
4563 /* Create res node if neccesary */
4565 for (l = type_node->children; l; l = l->next)
4566 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4567 res_node = (ResTreeNode*)l->data;
4572 res_node = g_new0 (ResTreeNode, 1);
4573 res_node->id = win32_res->res_id;
4574 type_node->children = g_slist_append (type_node->children, res_node);
4577 res_node->children = g_slist_append (res_node->children, lang_node);
4584 * resource_tree_encode:
4586 * Encode the resource tree into the format used in the PE file.
4589 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4592 MonoPEResourceDir dir;
4593 MonoPEResourceDirEntry dir_entry;
4594 MonoPEResourceDataEntry data_entry;
4598 * For the format of the resource directory, see the article
4599 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4603 memset (&dir, 0, sizeof (dir));
4604 memset (&dir_entry, 0, sizeof (dir_entry));
4605 memset (&data_entry, 0, sizeof (data_entry));
4607 g_assert (sizeof (dir) == 16);
4608 g_assert (sizeof (dir_entry) == 8);
4609 g_assert (sizeof (data_entry) == 16);
4611 node->offset = p - begin;
4613 /* IMAGE_RESOURCE_DIRECTORY */
4614 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4616 memcpy (p, &dir, sizeof (dir));
4619 /* Reserve space for entries */
4621 p += sizeof (dir_entry) * dir.res_id_entries;
4623 /* Write children */
4624 for (l = node->children; l; l = l->next) {
4625 ResTreeNode *child = (ResTreeNode*)l->data;
4627 if (child->win32_res) {
4629 child->offset = p - begin;
4631 /* IMAGE_RESOURCE_DATA_ENTRY */
4632 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4633 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4635 memcpy (p, &data_entry, sizeof (data_entry));
4636 p += sizeof (data_entry);
4638 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4639 p += data_entry.rde_size;
4641 resource_tree_encode (child, begin, p, &p);
4645 /* IMAGE_RESOURCE_ENTRY */
4646 for (l = node->children; l; l = l->next) {
4647 ResTreeNode *child = (ResTreeNode*)l->data;
4648 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4650 dir_entry.is_dir = child->win32_res ? 0 : 1;
4651 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4653 memcpy (entries, &dir_entry, sizeof (dir_entry));
4654 entries += sizeof (dir_entry);
4661 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4666 MonoReflectionWin32Resource *win32_res;
4669 if (!assemblyb->win32_resources)
4673 * Resources are stored in a three level tree inside the PE file.
4674 * - level one contains a node for each type of resource
4675 * - level two contains a node for each resource
4676 * - level three contains a node for each instance of a resource for a
4677 * specific language.
4680 tree = resource_tree_create (assemblyb->win32_resources);
4682 /* Estimate the size of the encoded tree */
4684 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4685 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4686 size += mono_array_length (win32_res->res_data);
4688 /* Directory structure */
4689 size += mono_array_length (assemblyb->win32_resources) * 256;
4690 p = buf = g_malloc (size);
4692 resource_tree_encode (tree, p, p, &p);
4694 g_assert (p - buf < size);
4696 assembly->win32_res = g_malloc (p - buf);
4697 assembly->win32_res_size = p - buf;
4698 memcpy (assembly->win32_res, buf, p - buf);
4704 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4706 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4709 p += sizeof (MonoPEResourceDir);
4710 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4711 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4712 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4713 if (dir_entry->is_dir) {
4714 fixup_resource_directory (res_section, child, rva);
4716 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4717 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4720 p += sizeof (MonoPEResourceDirEntry);
4725 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4728 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4729 g_error ("WriteFile returned %d\n", GetLastError ());
4733 * mono_image_create_pefile:
4734 * @mb: a module builder object
4736 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4737 * assembly->pefile where it can be easily retrieved later in chunks.
4740 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4741 MonoMSDOSHeader *msdos;
4742 MonoDotNetHeader *header;
4743 MonoSectionTable *section;
4744 MonoCLIHeader *cli_header;
4745 guint32 size, image_size, virtual_base, text_offset;
4746 guint32 header_start, section_start, file_offset, virtual_offset;
4747 MonoDynamicImage *assembly;
4748 MonoReflectionAssemblyBuilder *assemblyb;
4749 MonoDynamicStream pefile_stream = {0};
4750 MonoDynamicStream *pefile = &pefile_stream;
4752 guint32 *rva, value;
4754 static const unsigned char msheader[] = {
4755 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4756 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4757 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4758 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4759 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4760 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4761 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4762 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4765 assemblyb = mb->assemblyb;
4767 mono_image_basic_init (assemblyb);
4768 assembly = mb->dynamic_image;
4770 assembly->pe_kind = assemblyb->pe_kind;
4771 assembly->machine = assemblyb->machine;
4772 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4773 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4775 mono_image_build_metadata (mb);
4777 if (mb->is_main && assemblyb->resources) {
4778 int len = mono_array_length (assemblyb->resources);
4779 for (i = 0; i < len; ++i)
4780 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4783 if (mb->resources) {
4784 int len = mono_array_length (mb->resources);
4785 for (i = 0; i < len; ++i)
4786 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4789 build_compressed_metadata (assembly);
4792 assembly_add_win32_resources (assembly, assemblyb);
4794 nsections = calc_section_size (assembly);
4796 /* The DOS header and stub */
4797 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4798 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4800 /* the dotnet header */
4801 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4803 /* the section tables */
4804 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4806 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4807 virtual_offset = VIRT_ALIGN;
4810 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4811 if (!assembly->sections [i].size)
4814 file_offset += FILE_ALIGN - 1;
4815 file_offset &= ~(FILE_ALIGN - 1);
4816 virtual_offset += VIRT_ALIGN - 1;
4817 virtual_offset &= ~(VIRT_ALIGN - 1);
4819 assembly->sections [i].offset = file_offset;
4820 assembly->sections [i].rva = virtual_offset;
4822 file_offset += assembly->sections [i].size;
4823 virtual_offset += assembly->sections [i].size;
4824 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4827 file_offset += FILE_ALIGN - 1;
4828 file_offset &= ~(FILE_ALIGN - 1);
4830 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4832 /* back-patch info */
4833 msdos = (MonoMSDOSHeader*)pefile->data;
4834 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4836 header = (MonoDotNetHeader*)(pefile->data + header_start);
4837 header->pesig [0] = 'P';
4838 header->pesig [1] = 'E';
4840 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4841 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4842 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4843 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4844 if (assemblyb->pekind == 1) {
4846 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4849 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4852 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4854 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4855 header->pe.pe_major = 6;
4856 header->pe.pe_minor = 0;
4857 size = assembly->sections [MONO_SECTION_TEXT].size;
4858 size += FILE_ALIGN - 1;
4859 size &= ~(FILE_ALIGN - 1);
4860 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4861 size = assembly->sections [MONO_SECTION_RSRC].size;
4862 size += FILE_ALIGN - 1;
4863 size &= ~(FILE_ALIGN - 1);
4864 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4865 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4866 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4867 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4868 /* pe_rva_entry_point always at the beginning of the text section */
4869 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4871 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4872 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4873 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4874 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4875 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4876 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4877 size = section_start;
4878 size += FILE_ALIGN - 1;
4879 size &= ~(FILE_ALIGN - 1);
4880 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4882 size += VIRT_ALIGN - 1;
4883 size &= ~(VIRT_ALIGN - 1);
4884 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4887 // Translate the PEFileKind value to the value expected by the Windows loader
4893 // PEFileKinds.Dll == 1
4894 // PEFileKinds.ConsoleApplication == 2
4895 // PEFileKinds.WindowApplication == 3
4898 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4899 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4901 if (assemblyb->pekind == 3)
4906 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4908 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4909 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4910 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4911 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4912 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4913 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4915 /* fill data directory entries */
4917 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4918 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4920 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4921 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4923 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4924 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4925 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4926 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4927 /* patch entrypoint name */
4928 if (assemblyb->pekind == 1)
4929 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4931 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4932 /* patch imported function RVA name */
4933 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4934 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4936 /* the import table */
4937 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4938 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4939 /* patch imported dll RVA name and other entries in the dir */
4940 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4941 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4942 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4943 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4944 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4945 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4947 p = (assembly->code.data + assembly->ilt_offset);
4948 value = (assembly->text_rva + assembly->imp_names_offset);
4949 *p++ = (value) & 0xff;
4950 *p++ = (value >> 8) & (0xff);
4951 *p++ = (value >> 16) & (0xff);
4952 *p++ = (value >> 24) & (0xff);
4954 /* the CLI header info */
4955 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4956 cli_header->ch_size = GUINT32_FROM_LE (72);
4957 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4958 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4959 if (assemblyb->entry_point) {
4960 guint32 table_idx = 0;
4961 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4962 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4963 table_idx = methodb->table_idx;
4965 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4967 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4969 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4971 /* The embedded managed resources */
4972 text_offset = assembly->text_rva + assembly->code.index;
4973 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4974 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4975 text_offset += assembly->resources.index;
4976 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4977 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4978 text_offset += assembly->meta_size;
4979 if (assembly->strong_name_size) {
4980 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4981 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4982 text_offset += assembly->strong_name_size;
4985 /* write the section tables and section content */
4986 section = (MonoSectionTable*)(pefile->data + section_start);
4987 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4988 static const char *section_names [] = {
4989 ".text", ".rsrc", ".reloc"
4991 if (!assembly->sections [i].size)
4993 strcpy (section->st_name, section_names [i]);
4994 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4995 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4996 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4997 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4998 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4999 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5000 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5004 checked_write_file (file, pefile->data, pefile->index);
5006 mono_dynamic_stream_reset (pefile);
5008 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5009 if (!assembly->sections [i].size)
5012 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5013 g_error ("SetFilePointer returned %d\n", GetLastError ());
5016 case MONO_SECTION_TEXT:
5017 /* patch entry point */
5018 p = (assembly->code.data + 2);
5019 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5020 *p++ = (value) & 0xff;
5021 *p++ = (value >> 8) & 0xff;
5022 *p++ = (value >> 16) & 0xff;
5023 *p++ = (value >> 24) & 0xff;
5025 checked_write_file (file, assembly->code.data, assembly->code.index);
5026 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5027 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5028 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5031 g_free (assembly->image.raw_metadata);
5033 case MONO_SECTION_RELOC: {
5037 guint16 type_and_offset;
5041 g_assert (sizeof (reloc) == 12);
5043 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5044 reloc.block_size = GUINT32_FROM_LE (12);
5047 * the entrypoint is always at the start of the text section
5048 * 3 is IMAGE_REL_BASED_HIGHLOW
5049 * 2 is patch_size_rva - text_rva
5051 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5054 checked_write_file (file, &reloc, sizeof (reloc));
5058 case MONO_SECTION_RSRC:
5059 if (assembly->win32_res) {
5061 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5062 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5063 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5067 g_assert_not_reached ();
5071 /* check that the file is properly padded */
5072 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5073 g_error ("SetFilePointer returned %d\n", GetLastError ());
5074 if (! SetEndOfFile (file))
5075 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5077 mono_dynamic_stream_reset (&assembly->code);
5078 mono_dynamic_stream_reset (&assembly->us);
5079 mono_dynamic_stream_reset (&assembly->blob);
5080 mono_dynamic_stream_reset (&assembly->guid);
5081 mono_dynamic_stream_reset (&assembly->sheap);
5083 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5084 g_hash_table_destroy (assembly->blob_cache);
5085 assembly->blob_cache = NULL;
5088 MonoReflectionModule *
5089 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5093 MonoImageOpenStatus status;
5094 MonoDynamicAssembly *assembly;
5095 guint32 module_count;
5096 MonoImage **new_modules;
5098 name = mono_string_to_utf8 (fileName);
5100 image = mono_image_open (name, &status);
5103 if (status == MONO_IMAGE_ERROR_ERRNO)
5104 exc = mono_get_exception_file_not_found (fileName);
5106 exc = mono_get_exception_bad_image_format (name);
5108 mono_raise_exception (exc);
5113 assembly = ab->dynamic_assembly;
5114 image->assembly = (MonoAssembly*)assembly;
5116 module_count = image->assembly->image->module_count;
5117 new_modules = g_new0 (MonoImage *, module_count + 1);
5119 if (image->assembly->image->modules)
5120 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5121 new_modules [module_count] = image;
5122 mono_image_addref (image);
5124 g_free (image->assembly->image->modules);
5125 image->assembly->image->modules = new_modules;
5126 image->assembly->image->module_count ++;
5128 mono_assembly_load_references (image, &status);
5130 mono_image_close (image);
5131 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5134 return mono_module_get_object (mono_domain_get (), image);
5138 * We need to return always the same object for MethodInfo, FieldInfo etc..
5139 * but we need to consider the reflected type.
5140 * type uses a different hash, since it uses custom hash/equal functions.
5145 MonoClass *refclass;
5149 reflected_equal (gconstpointer a, gconstpointer b) {
5150 const ReflectedEntry *ea = a;
5151 const ReflectedEntry *eb = b;
5153 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5157 reflected_hash (gconstpointer a) {
5158 const ReflectedEntry *ea = a;
5159 return mono_aligned_addr_hash (ea->item);
5162 #define CHECK_OBJECT(t,p,k) \
5168 mono_domain_lock (domain); \
5169 if (!domain->refobject_hash) \
5170 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5171 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5172 mono_domain_unlock (domain); \
5175 mono_domain_unlock (domain); \
5179 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5181 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5183 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5186 #define CACHE_OBJECT(t,p,o,k) \
5189 ReflectedEntry pe; \
5191 pe.refclass = (k); \
5192 mono_domain_lock (domain); \
5193 if (!domain->refobject_hash) \
5194 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5195 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5197 ReflectedEntry *e = ALLOC_REFENTRY; \
5199 e->refclass = (k); \
5200 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5203 mono_domain_unlock (domain); \
5208 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5210 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5214 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5216 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5220 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5222 MonoDynamicImage *image = moduleb->dynamic_image;
5223 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5226 MonoImage **new_modules;
5229 * FIXME: we already created an image in mono_image_basic_init (), but
5230 * we don't know which module it belongs to, since that is only
5231 * determined at assembly save time.
5233 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5234 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5236 moduleb->module.image = &image->image;
5237 moduleb->dynamic_image = image;
5238 register_module (mono_object_domain (moduleb), moduleb, image);
5240 /* register the module with the assembly */
5241 ass = ab->dynamic_assembly->assembly.image;
5242 module_count = ass->module_count;
5243 new_modules = g_new0 (MonoImage *, module_count + 1);
5246 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5247 new_modules [module_count] = &image->image;
5248 mono_image_addref (&image->image);
5250 g_free (ass->modules);
5251 ass->modules = new_modules;
5252 ass->module_count ++;
5257 * mono_assembly_get_object:
5258 * @domain: an app domain
5259 * @assembly: an assembly
5261 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5263 MonoReflectionAssembly*
5264 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5266 static MonoClass *System_Reflection_Assembly;
5267 MonoReflectionAssembly *res;
5269 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5270 if (!System_Reflection_Assembly)
5271 System_Reflection_Assembly = mono_class_from_name (
5272 mono_defaults.corlib, "System.Reflection", "Assembly");
5273 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5274 res->assembly = assembly;
5276 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5281 MonoReflectionModule*
5282 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5284 static MonoClass *System_Reflection_Module;
5285 MonoReflectionModule *res;
5288 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5289 if (!System_Reflection_Module)
5290 System_Reflection_Module = mono_class_from_name (
5291 mono_defaults.corlib, "System.Reflection", "Module");
5292 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5295 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5297 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5298 basename = g_path_get_basename (image->name);
5299 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5300 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5304 if (image->assembly->image == image) {
5305 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5308 g_assert (image->assembly->image->modules);
5310 for (i = 0; i < image->assembly->image->module_count; i++) {
5311 if (image->assembly->image->modules [i] == image)
5312 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5314 g_assert (res->token);
5317 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5320 MonoReflectionModule*
5321 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5323 static MonoClass *System_Reflection_Module;
5324 MonoReflectionModule *res;
5325 MonoTableInfo *table;
5326 guint32 cols [MONO_FILE_SIZE];
5328 guint32 i, name_idx;
5331 if (!System_Reflection_Module)
5332 System_Reflection_Module = mono_class_from_name (
5333 mono_defaults.corlib, "System.Reflection", "Module");
5334 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5336 table = &image->tables [MONO_TABLE_FILE];
5337 g_assert (table_index < table->rows);
5338 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5341 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5342 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5344 /* Check whenever the row has a corresponding row in the moduleref table */
5345 table = &image->tables [MONO_TABLE_MODULEREF];
5346 for (i = 0; i < table->rows; ++i) {
5347 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5348 val = mono_metadata_string_heap (image, name_idx);
5349 if (strcmp (val, name) == 0)
5350 res->image = image->modules [i];
5353 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5354 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5355 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5356 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5357 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5363 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5365 if ((t1->type != t2->type) ||
5366 (t1->byref != t2->byref))
5370 case MONO_TYPE_VOID:
5371 case MONO_TYPE_BOOLEAN:
5372 case MONO_TYPE_CHAR:
5383 case MONO_TYPE_STRING:
5386 case MONO_TYPE_OBJECT:
5387 case MONO_TYPE_TYPEDBYREF:
5389 case MONO_TYPE_VALUETYPE:
5390 case MONO_TYPE_CLASS:
5391 case MONO_TYPE_SZARRAY:
5392 return t1->data.klass == t2->data.klass;
5394 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5395 case MONO_TYPE_ARRAY:
5396 if (t1->data.array->rank != t2->data.array->rank)
5398 return t1->data.array->eklass == t2->data.array->eklass;
5399 case MONO_TYPE_GENERICINST: {
5401 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5403 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5404 &t2->data.generic_class->container_class->byval_arg))
5406 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5407 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5413 case MONO_TYPE_MVAR:
5414 return t1->data.generic_param == t2->data.generic_param;
5416 g_error ("implement type compare for %0x!", t1->type);
5424 mymono_metadata_type_hash (MonoType *t1)
5430 hash |= t1->byref << 6; /* do not collide with t1->type values */
5432 case MONO_TYPE_VALUETYPE:
5433 case MONO_TYPE_CLASS:
5434 case MONO_TYPE_SZARRAY:
5435 /* check if the distribution is good enough */
5436 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5438 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5439 case MONO_TYPE_GENERICINST: {
5441 MonoGenericInst *inst = t1->data.generic_class->inst;
5442 hash += g_str_hash (t1->data.generic_class->container_class->name);
5444 for (i = 0; i < inst->type_argc; ++i) {
5445 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5454 static MonoReflectionGenericClass*
5455 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5457 static MonoClass *System_Reflection_MonoGenericClass;
5458 MonoReflectionGenericClass *res;
5459 MonoInflatedGenericClass *gclass;
5462 if (!System_Reflection_MonoGenericClass) {
5463 System_Reflection_MonoGenericClass = mono_class_from_name (
5464 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5465 g_assert (System_Reflection_MonoGenericClass);
5468 gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
5469 gklass = gclass->generic_class.container_class;
5470 g_assert (gklass->generic_container);
5472 mono_class_init (gclass->klass);
5474 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5476 res->type.type = geninst;
5477 if (gklass->wastypebuilder && gklass->reflection_info)
5478 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5480 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5486 verify_safe_for_managed_space (MonoType *type)
5488 switch (type->type) {
5490 case MONO_TYPE_ARRAY:
5491 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5493 return verify_safe_for_managed_space (type->data.type);
5494 case MONO_TYPE_SZARRAY:
5495 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5496 case MONO_TYPE_GENERICINST: {
5497 MonoGenericInst *inst = type->data.generic_class->inst;
5501 for (i = 0; i < inst->type_argc; ++i)
5502 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5508 case MONO_TYPE_MVAR:
5509 return type->data.generic_param->owner != NULL;
5515 * mono_type_get_object:
5516 * @domain: an app domain
5519 * Return an System.MonoType object representing the type @type.
5522 mono_type_get_object (MonoDomain *domain, MonoType *type)
5524 MonoReflectionType *res;
5525 MonoClass *klass = mono_class_from_mono_type (type);
5527 mono_domain_lock (domain);
5528 if (!domain->type_hash)
5529 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5530 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5531 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5532 mono_domain_unlock (domain);
5535 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5536 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5537 mono_g_hash_table_insert (domain->type_hash, type, res);
5538 mono_domain_unlock (domain);
5542 if (!verify_safe_for_managed_space (type)) {
5543 mono_domain_unlock (domain);
5544 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5547 if (klass->reflection_info && !klass->wastypebuilder) {
5548 /* g_assert_not_reached (); */
5549 /* should this be considered an error condition? */
5551 mono_domain_unlock (domain);
5552 return klass->reflection_info;
5555 mono_class_init (klass);
5557 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5559 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5562 mono_g_hash_table_insert (domain->type_hash, type, res);
5563 mono_domain_unlock (domain);
5568 * mono_method_get_object:
5569 * @domain: an app domain
5571 * @refclass: the reflected type (can be NULL)
5573 * Return an System.Reflection.MonoMethod object representing the method @method.
5575 MonoReflectionMethod*
5576 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5579 * We use the same C representation for methods and constructors, but the type
5580 * name in C# is different.
5584 MonoReflectionMethod *ret;
5586 if (method->is_inflated) {
5587 MonoReflectionGenericMethod *gret;
5589 method = mono_get_inflated_method (method);
5590 refclass = method->klass;
5591 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5592 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5593 cname = "MonoGenericCMethod";
5595 cname = "MonoGenericMethod";
5596 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5598 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5599 gret->method.method = method;
5600 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5601 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5602 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5606 refclass = method->klass;
5608 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5609 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5610 cname = "MonoCMethod";
5612 cname = "MonoMethod";
5613 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5615 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5616 ret->method = method;
5617 MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name));
5618 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5619 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5623 * mono_field_get_object:
5624 * @domain: an app domain
5628 * Return an System.Reflection.MonoField object representing the field @field
5631 MonoReflectionField*
5632 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5634 MonoReflectionField *res;
5637 CHECK_OBJECT (MonoReflectionField *, field, klass);
5638 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5639 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5642 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5643 if (field->generic_info)
5644 res->attrs = field->generic_info->generic_type->attrs;
5646 res->attrs = field->type->attrs;
5647 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5648 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5652 * mono_property_get_object:
5653 * @domain: an app domain
5655 * @property: a property
5657 * Return an System.Reflection.MonoProperty object representing the property @property
5660 MonoReflectionProperty*
5661 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5663 MonoReflectionProperty *res;
5666 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5667 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5668 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5670 res->property = property;
5671 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5675 * mono_event_get_object:
5676 * @domain: an app domain
5680 * Return an System.Reflection.MonoEvent object representing the event @event
5683 MonoReflectionEvent*
5684 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5686 MonoReflectionEvent *res;
5689 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5690 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5691 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5694 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5698 * mono_param_get_objects:
5699 * @domain: an app domain
5702 * Return an System.Reflection.ParameterInfo array object representing the parameters
5703 * in the method @method.
5706 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5708 static MonoClass *System_Reflection_ParameterInfo;
5709 MonoArray *res = NULL;
5710 MonoReflectionMethod *member = NULL;
5711 MonoReflectionParameter *param = NULL;
5712 char **names, **blobs = NULL;
5713 guint32 *types = NULL;
5714 MonoType *type = NULL;
5715 MonoObject *dbnull = mono_get_dbnull_object (domain);
5716 MonoMarshalSpec **mspecs;
5719 if (!System_Reflection_ParameterInfo)
5720 System_Reflection_ParameterInfo = mono_class_from_name (
5721 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5723 if (!mono_method_signature (method)->param_count)
5724 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5726 /* Note: the cache is based on the address of the signature into the method
5727 * since we already cache MethodInfos with the method as keys.
5729 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5731 member = mono_method_get_object (domain, method, NULL);
5732 names = g_new (char *, mono_method_signature (method)->param_count);
5733 mono_method_get_param_names (method, (const char **) names);
5735 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
5736 mono_method_get_marshal_info (method, mspecs);
5738 res = mono_array_new (domain, System_Reflection_ParameterInfo, mono_method_signature (method)->param_count);
5739 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
5740 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5741 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, mono_method_signature (method)->params [i]));
5742 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5743 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5744 param->PositionImpl = i;
5745 param->AttrsImpl = mono_method_signature (method)->params [i]->attrs;
5747 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5748 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5752 blobs = g_new0 (char *, mono_method_signature (method)->param_count);
5753 types = g_new0 (guint32, mono_method_signature (method)->param_count);
5754 get_default_param_value_blobs (method, blobs, types);
5757 /* Build MonoType for the type from the Constant Table */
5759 type = g_new0 (MonoType, 1);
5760 type->type = types [i];
5761 type->data.klass = NULL;
5762 if (types [i] == MONO_TYPE_CLASS)
5763 type->data.klass = mono_defaults.object_class;
5765 type->data.klass = mono_class_from_mono_type (type);
5767 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5769 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5770 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5771 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5776 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5778 mono_array_setref (res, i, param);
5785 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5787 mono_metadata_free_marshal_spec (mspecs [i]);
5790 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5794 * mono_method_body_get_object:
5795 * @domain: an app domain
5798 * Return an System.Reflection.MethodBody object representing the method @method.
5800 MonoReflectionMethodBody*
5801 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5803 static MonoClass *System_Reflection_MethodBody = NULL;
5804 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5805 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5806 MonoReflectionMethodBody *ret;
5807 MonoMethodNormal *mn;
5808 MonoMethodHeader *header;
5809 guint32 method_rva, local_var_sig_token;
5811 unsigned char format, flags;
5814 if (!System_Reflection_MethodBody)
5815 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5816 if (!System_Reflection_LocalVariableInfo)
5817 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5818 if (!System_Reflection_ExceptionHandlingClause)
5819 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5821 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5823 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5824 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5825 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5826 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5828 mn = (MonoMethodNormal *)method;
5829 header = mono_method_get_header (method);
5831 /* Obtain local vars signature token */
5832 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5833 ptr = mono_image_rva_map (method->klass->image, method_rva);
5834 flags = *(const unsigned char *) ptr;
5835 format = flags & METHOD_HEADER_FORMAT_MASK;
5837 case METHOD_HEADER_TINY_FORMAT:
5838 case METHOD_HEADER_TINY_FORMAT1:
5839 local_var_sig_token = 0;
5841 case METHOD_HEADER_FAT_FORMAT:
5845 local_var_sig_token = read32 (ptr);
5848 g_assert_not_reached ();
5851 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5853 ret->init_locals = header->init_locals;
5854 ret->max_stack = header->max_stack;
5855 ret->local_var_sig_token = local_var_sig_token;
5856 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5857 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5860 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5861 for (i = 0; i < header->num_locals; ++i) {
5862 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5863 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5864 info->is_pinned = header->locals [i]->pinned;
5865 info->local_index = i;
5866 mono_array_setref (ret->locals, i, info);
5870 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5871 for (i = 0; i < header->num_clauses; ++i) {
5872 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5873 MonoExceptionClause *clause = &header->clauses [i];
5875 info->flags = clause->flags;
5876 info->try_offset = clause->try_offset;
5877 info->try_length = clause->try_len;
5878 info->handler_offset = clause->handler_offset;
5879 info->handler_length = clause->handler_len;
5880 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5881 info->filter_offset = clause->data.filter_offset;
5882 else if (clause->data.catch_class)
5883 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5885 mono_array_setref (ret->clauses, i, info);
5888 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5893 mono_get_dbnull_object (MonoDomain *domain)
5897 static MonoClassField *dbnull_value_field = NULL;
5899 if (!dbnull_value_field) {
5900 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5901 mono_class_init (klass);
5902 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5903 g_assert (dbnull_value_field);
5905 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5912 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5914 guint32 param_index, i, lastp, crow = 0;
5915 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5918 MonoClass *klass = method->klass;
5919 MonoImage *image = klass->image;
5920 MonoMethodSignature *methodsig = mono_method_signature (method);
5922 MonoTableInfo *constt;
5923 MonoTableInfo *methodt;
5924 MonoTableInfo *paramt;
5926 if (!methodsig->param_count)
5929 mono_class_init (klass);
5931 if (klass->image->dynamic) {
5932 MonoReflectionMethodAux *aux;
5933 if (method->is_inflated)
5934 method = ((MonoMethodInflated*)method)->declaring;
5935 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5936 if (aux && aux->param_defaults) {
5937 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5938 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5943 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5944 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5945 constt = &image->tables [MONO_TABLE_CONSTANT];
5947 idx = mono_method_get_index (method) - 1;
5948 g_assert (idx != -1);
5950 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5951 if (idx + 1 < methodt->rows)
5952 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5954 lastp = paramt->rows + 1;
5956 for (i = param_index; i < lastp; ++i) {
5959 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5960 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5962 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5965 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5970 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5971 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5972 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5979 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5984 MonoType *basetype = type;
5989 klass = mono_class_from_mono_type (type);
5990 if (klass->valuetype) {
5991 object = mono_object_new (domain, klass);
5992 retval = ((gchar *) object + sizeof (MonoObject));
5993 if (klass->enumtype)
5994 basetype = klass->enum_basetype;
5999 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6006 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6010 memset (assembly, 0, sizeof (MonoAssemblyName));
6012 assembly->culture = "";
6013 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6015 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6018 while (g_ascii_isspace (*p) || *p == ',') {
6027 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6029 assembly->major = strtoul (p, &s, 10);
6030 if (s == p || *s != '.')
6033 assembly->minor = strtoul (p, &s, 10);
6034 if (s == p || *s != '.')
6037 assembly->build = strtoul (p, &s, 10);
6038 if (s == p || *s != '.')
6041 assembly->revision = strtoul (p, &s, 10);
6045 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6047 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6048 assembly->culture = "";
6051 assembly->culture = p;
6052 while (*p && *p != ',') {
6056 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6058 if (strncmp (p, "null", 4) == 0) {
6063 while (*p && *p != ',') {
6066 len = (p - start + 1);
6067 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6068 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6069 g_strlcpy (assembly->public_key_token, start, len);
6072 while (*p && *p != ',')
6076 while (g_ascii_isspace (*p) || *p == ',') {
6090 * mono_reflection_parse_type:
6093 * Parse a type name as accepted by the GetType () method and output the info
6094 * extracted in the info structure.
6095 * the name param will be mangled, so, make a copy before passing it to this function.
6096 * The fields in info will be valid until the memory pointed to by name is valid.
6098 * See also mono_type_get_name () below.
6100 * Returns: 0 on parse error.
6103 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6104 MonoTypeNameParse *info)
6106 char *start, *p, *w, *temp, *last_point, *startn;
6107 int in_modifiers = 0;
6108 int isbyref = 0, rank, arity = 0, i;
6110 start = p = w = name;
6112 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6113 info->name = info->name_space = NULL;
6114 info->nested = NULL;
6115 info->modifiers = NULL;
6116 info->type_arguments = NULL;
6118 /* last_point separates the namespace from the name */
6124 *p = 0; /* NULL terminate the name */
6126 info->nested = g_list_append (info->nested, startn);
6127 /* we have parsed the nesting namespace + name */
6131 info->name_space = start;
6133 info->name = last_point + 1;
6135 info->name_space = (char *)"";
6154 i = strtol (p, &temp, 10);
6171 info->name_space = start;
6173 info->name = last_point + 1;
6175 info->name_space = (char *)"";
6182 if (isbyref) /* only one level allowed by the spec */
6185 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6189 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6195 info->type_arguments = g_ptr_array_new ();
6196 for (i = 0; i < arity; i++) {
6197 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6198 gboolean fqname = FALSE;
6200 g_ptr_array_add (info->type_arguments, subinfo);
6207 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6218 while (*p && (*p != ']'))
6226 if (g_ascii_isspace (*aname)) {
6233 !assembly_name_to_aname (&subinfo->assembly, aname))
6237 if (i + 1 < arity) {
6257 else if (*p != '*') /* '*' means unknown lower bound */
6263 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6274 if (g_ascii_isspace (*p)) {
6281 return 0; /* missing assembly name */
6282 if (!assembly_name_to_aname (&info->assembly, p))
6288 if (info->assembly.name)
6291 // *w = 0; /* terminate class name */
6293 if (!info->name || !*info->name)
6297 /* add other consistency checks */
6302 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6304 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6308 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6310 gboolean type_resolve = FALSE;
6313 if (info->assembly.name) {
6314 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6316 /* then we must load the assembly ourselve - see #60439 */
6317 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6321 image = assembly->image;
6322 } else if (!image) {
6323 image = mono_defaults.corlib;
6326 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6327 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6328 image = mono_defaults.corlib;
6329 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6336 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6343 image = mono_defaults.corlib;
6346 klass = mono_class_from_name_case (image, info->name_space, info->name);
6348 klass = mono_class_from_name (image, info->name_space, info->name);
6351 for (mod = info->nested; mod; mod = mod->next) {
6354 mono_class_init (klass);
6355 nested = klass->nested_classes;
6358 klass = nested->data;
6360 if (g_strcasecmp (klass->name, mod->data) == 0)
6363 if (strcmp (klass->name, mod->data) == 0)
6367 nested = nested->next;
6374 mono_class_init (klass);
6376 if (info->type_arguments) {
6377 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6378 MonoReflectionType *the_type;
6382 for (i = 0; i < info->type_arguments->len; i++) {
6383 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6385 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6386 if (!type_args [i]) {
6392 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6394 instance = mono_reflection_bind_generic_parameters (
6395 the_type, info->type_arguments->len, type_args);
6402 klass = mono_class_from_mono_type (instance);
6405 for (mod = info->modifiers; mod; mod = mod->next) {
6406 modval = GPOINTER_TO_UINT (mod->data);
6407 if (!modval) { /* byref: must be last modifier */
6408 return &klass->this_arg;
6409 } else if (modval == -1) {
6410 klass = mono_ptr_class_get (&klass->byval_arg);
6411 } else { /* array rank */
6412 klass = mono_array_class_get (klass, modval);
6414 mono_class_init (klass);
6417 return &klass->byval_arg;
6421 * mono_reflection_get_type:
6422 * @image: a metadata context
6423 * @info: type description structure
6424 * @ignorecase: flag for case-insensitive string compares
6425 * @type_resolve: whenever type resolve was already tried
6427 * Build a MonoType from the type description in @info.
6432 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6435 MonoReflectionAssembly *assembly;
6439 type = mono_reflection_get_type_internal (image, info, ignorecase);
6442 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6449 *type_resolve = TRUE;
6452 /* Reconstruct the type name */
6453 fullName = g_string_new ("");
6454 if (info->name_space && (info->name_space [0] != '\0'))
6455 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6457 g_string_printf (fullName, info->name);
6458 for (mod = info->nested; mod; mod = mod->next)
6459 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6461 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6463 if (assembly->assembly->dynamic) {
6464 /* Enumerate all modules */
6465 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6469 if (abuilder->modules) {
6470 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6471 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6472 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6478 if (!type && abuilder->loaded_modules) {
6479 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6480 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6481 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6488 type = mono_reflection_get_type_internal (assembly->assembly->image,
6491 g_string_free (fullName, TRUE);
6496 free_type_info (MonoTypeNameParse *info)
6498 g_list_free (info->modifiers);
6499 g_list_free (info->nested);
6501 if (info->type_arguments) {
6504 for (i = 0; i < info->type_arguments->len; i++) {
6505 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6507 free_type_info (subinfo);
6510 g_ptr_array_free (info->type_arguments, TRUE);
6515 * mono_reflection_type_from_name:
6517 * @image: a metadata context (can be NULL).
6519 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6520 * it defaults to get the type from @image or, if @image is NULL or loading
6521 * from it fails, uses corlib.
6525 mono_reflection_type_from_name (char *name, MonoImage *image)
6527 MonoType *type = NULL;
6528 MonoTypeNameParse info;
6531 /* Make a copy since parse_type modifies its argument */
6532 tmp = g_strdup (name);
6534 /*g_print ("requested type %s\n", str);*/
6535 if (mono_reflection_parse_type (tmp, &info)) {
6536 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6540 free_type_info (&info);
6545 * mono_reflection_get_token:
6547 * Return the metadata token of OBJ which should be an object
6548 * representing a metadata element.
6551 mono_reflection_get_token (MonoObject *obj)
6556 klass = obj->vtable->klass;
6558 if (strcmp (klass->name, "MethodBuilder") == 0) {
6559 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6561 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6562 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6563 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6565 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6566 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6567 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6568 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6569 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6570 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6571 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6572 } else if (strcmp (klass->name, "MonoType") == 0) {
6573 MonoReflectionType *tb = (MonoReflectionType *)obj;
6574 token = mono_class_from_mono_type (tb->type)->type_token;
6575 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6576 strcmp (klass->name, "MonoMethod") == 0 ||
6577 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6578 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6579 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6580 if (m->method->is_inflated) {
6581 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6582 return inflated->declaring->token;
6584 token = m->method->token;
6586 } else if (strcmp (klass->name, "MonoField") == 0) {
6587 MonoReflectionField *f = (MonoReflectionField*)obj;
6589 if (f->field->generic_info && f->field->generic_info->reflection_info)
6590 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6592 token = mono_class_get_field_token (f->field);
6593 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6594 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6596 token = mono_class_get_property_token (p->property);
6597 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6598 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6600 token = mono_class_get_event_token (p->event);
6601 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6602 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6604 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6605 } else if (strcmp (klass->name, "Module") == 0) {
6606 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6609 } else if (strcmp (klass->name, "Assembly") == 0) {
6610 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6612 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6613 MonoException *ex = mono_get_exception_not_implemented (msg);
6615 mono_raise_exception (ex);
6622 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6624 int slen, type = t->type;
6625 MonoClass *tklass = t->data.klass;
6631 case MONO_TYPE_BOOLEAN: {
6632 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6637 case MONO_TYPE_CHAR:
6639 case MONO_TYPE_I2: {
6640 guint16 *val = g_malloc (sizeof (guint16));
6645 #if SIZEOF_VOID_P == 4
6651 case MONO_TYPE_I4: {
6652 guint32 *val = g_malloc (sizeof (guint32));
6657 #if SIZEOF_VOID_P == 8
6658 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6663 case MONO_TYPE_I8: {
6664 guint64 *val = g_malloc (sizeof (guint64));
6669 case MONO_TYPE_VALUETYPE:
6670 if (t->data.klass->enumtype) {
6671 type = t->data.klass->enum_basetype->type;
6674 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6677 case MONO_TYPE_STRING:
6678 if (*p == (char)0xFF) {
6682 slen = mono_metadata_decode_value (p, &p);
6684 return mono_string_new_len (mono_domain_get (), p, slen);
6685 case MONO_TYPE_CLASS: {
6688 if (*p == (char)0xFF) {
6693 slen = mono_metadata_decode_value (p, &p);
6694 n = g_memdup (p, slen + 1);
6696 t = mono_reflection_type_from_name (n, image);
6698 g_warning ("Cannot load type '%s'", n);
6702 return mono_type_get_object (mono_domain_get (), t);
6706 case MONO_TYPE_OBJECT: {
6709 MonoClass *subc = NULL;
6714 } else if (subt == 0x0E) {
6715 type = MONO_TYPE_STRING;
6717 } else if (subt == 0x1D) {
6718 MonoType simple_type = {{0}};
6722 type = MONO_TYPE_SZARRAY;
6723 simple_type.type = etype;
6724 tklass = mono_class_from_mono_type (&simple_type);
6726 } else if (subt == 0x55) {
6729 slen = mono_metadata_decode_value (p, &p);
6730 n = g_memdup (p, slen + 1);
6732 t = mono_reflection_type_from_name (n, image);
6734 g_warning ("Cannot load type '%s'", n);
6737 subc = mono_class_from_mono_type (t);
6738 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6739 MonoType simple_type = {{0}};
6740 simple_type.type = subt;
6741 subc = mono_class_from_mono_type (&simple_type);
6743 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6745 val = load_cattr_value (image, &subc->byval_arg, p, end);
6746 obj = mono_object_new (mono_domain_get (), subc);
6747 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6751 case MONO_TYPE_SZARRAY: {
6753 guint32 i, alen, basetype;
6756 if (alen == 0xffffffff) {
6760 arr = mono_array_new (mono_domain_get(), tklass, alen);
6761 basetype = tklass->byval_arg.type;
6766 case MONO_TYPE_BOOLEAN:
6767 for (i = 0; i < alen; i++) {
6768 MonoBoolean val = *p++;
6769 mono_array_set (arr, MonoBoolean, i, val);
6772 case MONO_TYPE_CHAR:
6775 for (i = 0; i < alen; i++) {
6776 guint16 val = read16 (p);
6777 mono_array_set (arr, guint16, i, val);
6784 for (i = 0; i < alen; i++) {
6785 guint32 val = read32 (p);
6786 mono_array_set (arr, guint32, i, val);
6793 for (i = 0; i < alen; i++) {
6794 guint64 val = read64 (p);
6795 mono_array_set (arr, guint64, i, val);
6799 case MONO_TYPE_CLASS:
6800 case MONO_TYPE_OBJECT:
6801 case MONO_TYPE_STRING:
6802 for (i = 0; i < alen; i++) {
6803 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6804 mono_array_setref (arr, i, item);
6808 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6814 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6820 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6822 static MonoClass *klass;
6823 static MonoMethod *ctor;
6825 void *params [2], *unboxed;
6828 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6830 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6832 params [0] = mono_type_get_object (mono_domain_get (), t);
6834 retval = mono_object_new (mono_domain_get (), klass);
6835 unboxed = mono_object_unbox (retval);
6836 mono_runtime_invoke (ctor, unboxed, params, NULL);
6842 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6844 static MonoClass *klass;
6845 static MonoMethod *ctor;
6847 void *unboxed, *params [2];
6850 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6852 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6855 params [1] = typedarg;
6856 retval = mono_object_new (mono_domain_get (), klass);
6857 unboxed = mono_object_unbox (retval);
6858 mono_runtime_invoke (ctor, unboxed, params, NULL);
6864 type_is_reference (MonoType *type)
6866 switch (type->type) {
6867 case MONO_TYPE_BOOLEAN:
6868 case MONO_TYPE_CHAR:
6881 case MONO_TYPE_VALUETYPE:
6889 free_param_data (MonoMethodSignature *sig, void **params) {
6891 for (i = 0; i < sig->param_count; ++i) {
6892 if (!type_is_reference (sig->params [i]))
6893 g_free (params [i]);
6898 * Find the field index in the metadata FieldDef table.
6901 find_field_index (MonoClass *klass, MonoClassField *field) {
6904 for (i = 0; i < klass->field.count; ++i) {
6905 if (field == &klass->fields [i])
6906 return klass->field.first + 1 + i;
6912 * Find the property index in the metadata Property table.
6915 find_property_index (MonoClass *klass, MonoProperty *property) {
6918 for (i = 0; i < klass->property.count; ++i) {
6919 if (property == &klass->properties [i])
6920 return klass->property.first + 1 + i;
6926 * Find the event index in the metadata Event table.
6929 find_event_index (MonoClass *klass, MonoEvent *event) {
6932 for (i = 0; i < klass->event.count; ++i) {
6933 if (event == &klass->events [i])
6934 return klass->event.first + 1 + i;
6940 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6942 const char *p = data;
6944 guint32 i, j, num_named;
6948 mono_class_init (method->klass);
6951 attr = mono_object_new (mono_domain_get (), method->klass);
6952 mono_runtime_invoke (method, attr, NULL, NULL);
6956 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6959 /*g_print ("got attr %s\n", method->klass->name);*/
6961 /* Allocate using alloca so it gets GC tracking */
6962 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6966 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6967 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6971 attr = mono_object_new (mono_domain_get (), method->klass);
6972 mono_runtime_invoke (method, attr, params, NULL);
6973 free_param_data (method->signature, params);
6974 num_named = read16 (named);
6976 for (j = 0; j < num_named; j++) {
6978 gboolean is_boxed = FALSE;
6979 char *name, named_type, data_type;
6980 named_type = *named++;
6981 data_type = *named++; /* type of data */
6982 if (data_type == 0x51)
6985 if (data_type == 0x55) {
6988 type_len = mono_metadata_decode_blob_size (named, &named);
6989 type_name = g_malloc (type_len + 1);
6990 memcpy (type_name, named, type_len);
6991 type_name [type_len] = 0;
6993 /* FIXME: lookup the type and check type consistency */
6995 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6996 /* this seems to be the type of the element of the array */
6997 /* g_print ("skipping 0x%02x after prop\n", *named); */
7000 name_len = mono_metadata_decode_blob_size (named, &named);
7001 name = g_malloc (name_len + 1);
7002 memcpy (name, named, name_len);
7003 name [name_len] = 0;
7005 if (named_type == 0x53) {
7006 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7007 void *val = load_cattr_value (image, field->type, named, &named);
7008 mono_field_set_value (attr, field, val);
7009 if (!type_is_reference (field->type))
7011 } else if (named_type == 0x54) {
7014 MonoType *prop_type;
7016 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7017 /* can we have more that 1 arg in a custom attr named property? */
7018 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7019 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7020 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7021 mono_property_set_value (prop, attr, pparams, NULL);
7022 if (!type_is_reference (prop_type))
7023 g_free (pparams [0]);
7032 create_custom_attr_data (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
7034 MonoArray *typedargs, *namedargs;
7035 MonoClass *attrklass;
7036 static MonoClass *klass;
7037 static MonoMethod *ctor;
7040 const char *p = data;
7042 guint32 i, j, num_named;
7045 mono_class_init (method->klass);
7048 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7050 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
7052 domain = mono_domain_get ();
7054 /* This is for Attributes with no parameters */
7055 attr = mono_object_new (domain, klass);
7056 params [0] = mono_method_get_object (domain, method, NULL);
7057 params [1] = params [2] = NULL;
7058 mono_runtime_invoke (method, attr, params, NULL);
7062 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7065 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7069 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7070 MonoObject *obj, *typedarg;
7073 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7074 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7075 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7076 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7077 mono_array_setref (typedargs, i, typedarg);
7079 if (!type_is_reference (mono_method_signature (method)->params [i]))
7084 num_named = read16 (named);
7085 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7087 attrklass = method->klass;
7088 for (j = 0; j < num_named; j++) {
7090 char *name, named_type, data_type;
7091 named_type = *named++;
7092 data_type = *named++; /* type of data */
7093 if (data_type == 0x55) {
7096 type_len = mono_metadata_decode_blob_size (named, &named);
7097 type_name = g_malloc (type_len + 1);
7098 memcpy (type_name, named, type_len);
7099 type_name [type_len] = 0;
7101 /* FIXME: lookup the type and check type consistency */
7103 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
7104 /* this seems to be the type of the element of the array */
7105 /* g_print ("skipping 0x%02x after prop\n", *named); */
7108 name_len = mono_metadata_decode_blob_size (named, &named);
7109 name = g_malloc (name_len + 1);
7110 memcpy (name, named, name_len);
7111 name [name_len] = 0;
7113 if (named_type == 0x53) {
7114 MonoObject *obj, *typedarg, *namedarg;
7115 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7116 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7118 minfo = mono_field_get_object (domain, NULL, field);
7119 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7120 typedarg = create_cattr_typed_arg (field->type, obj);
7121 namedarg = create_cattr_named_arg (minfo, typedarg);
7122 mono_array_setref (namedargs, j, namedarg);
7123 if (!type_is_reference (field->type))
7125 } else if (named_type == 0x54) {
7126 MonoObject *obj, *typedarg, *namedarg;
7127 MonoType *prop_type;
7129 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7131 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7132 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7133 minfo = mono_property_get_object (domain, NULL, prop);
7134 val = load_cattr_value (image, prop_type, named, &named);
7135 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7136 typedarg = create_cattr_typed_arg (prop_type, obj);
7137 namedarg = create_cattr_named_arg (minfo, typedarg);
7138 mono_array_setref (namedargs, j, namedarg);
7139 if (!type_is_reference (prop_type))
7144 attr = mono_object_new (domain, klass);
7145 params [0] = mono_method_get_object (domain, method, NULL);
7146 params [1] = typedargs;
7147 params [2] = namedargs;
7148 mono_runtime_invoke (ctor, attr, params, NULL);
7153 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7160 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7161 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7162 for (i = 0; i < cinfo->num_attrs; ++i) {
7163 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7164 mono_array_setref (result, i, attr);
7170 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7178 for (i = 0; i < cinfo->num_attrs; ++i) {
7179 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7183 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7184 result = mono_array_new (mono_domain_get (), klass, n);
7186 for (i = 0; i < cinfo->num_attrs; ++i) {
7187 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7188 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7189 mono_array_setref (result, n, attr);
7197 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7200 static MonoClass *klass;
7205 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7207 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7208 for (i = 0; i < cinfo->num_attrs; ++i) {
7209 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7210 mono_array_setref (result, i, attr);
7216 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7218 guint32 mtoken, i, len;
7219 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7221 MonoCustomAttrInfo *ainfo;
7222 GList *tmp, *list = NULL;
7225 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7227 i = mono_metadata_custom_attrs_from_index (image, idx);
7231 while (i < ca->rows) {
7232 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7234 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7237 len = g_list_length (list);
7240 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7241 ainfo->num_attrs = len;
7242 ainfo->image = image;
7243 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7244 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7245 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7246 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7247 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7248 mtoken |= MONO_TOKEN_METHOD_DEF;
7250 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7251 mtoken |= MONO_TOKEN_MEMBER_REF;
7254 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7257 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7258 if (!ainfo->attrs [i].ctor)
7259 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7260 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7261 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7262 ainfo->attrs [i].data = data;
7270 mono_custom_attrs_from_method (MonoMethod *method)
7272 MonoCustomAttrInfo *cinfo;
7275 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7277 idx = mono_method_get_index (method);
7278 idx <<= MONO_CUSTOM_ATTR_BITS;
7279 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7280 return mono_custom_attrs_from_index (method->klass->image, idx);
7284 mono_custom_attrs_from_class (MonoClass *klass)
7286 MonoCustomAttrInfo *cinfo;
7289 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7291 idx = mono_metadata_token_index (klass->type_token);
7292 idx <<= MONO_CUSTOM_ATTR_BITS;
7293 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7294 return mono_custom_attrs_from_index (klass->image, idx);
7298 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7300 MonoCustomAttrInfo *cinfo;
7303 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7305 idx = 1; /* there is only one assembly */
7306 idx <<= MONO_CUSTOM_ATTR_BITS;
7307 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7308 return mono_custom_attrs_from_index (assembly->image, idx);
7311 static MonoCustomAttrInfo*
7312 mono_custom_attrs_from_module (MonoImage *image)
7314 MonoCustomAttrInfo *cinfo;
7317 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7319 idx = 1; /* there is only one module */
7320 idx <<= MONO_CUSTOM_ATTR_BITS;
7321 idx |= MONO_CUSTOM_ATTR_MODULE;
7322 return mono_custom_attrs_from_index (image, idx);
7326 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7328 MonoCustomAttrInfo *cinfo;
7331 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7333 idx = find_property_index (klass, property);
7334 idx <<= MONO_CUSTOM_ATTR_BITS;
7335 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7336 return mono_custom_attrs_from_index (klass->image, idx);
7340 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7342 MonoCustomAttrInfo *cinfo;
7345 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7347 idx = find_event_index (klass, event);
7348 idx <<= MONO_CUSTOM_ATTR_BITS;
7349 idx |= MONO_CUSTOM_ATTR_EVENT;
7350 return mono_custom_attrs_from_index (klass->image, idx);
7354 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7356 MonoCustomAttrInfo *cinfo;
7359 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7361 idx = find_field_index (klass, field);
7362 idx <<= MONO_CUSTOM_ATTR_BITS;
7363 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7364 return mono_custom_attrs_from_index (klass->image, idx);
7368 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7371 guint32 i, idx, method_index;
7372 guint32 param_list, param_last, param_pos, found;
7374 MonoReflectionMethodAux *aux;
7376 if (method->klass->image->dynamic) {
7377 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7378 if (!aux || !aux->param_cattr)
7380 return aux->param_cattr [param];
7383 image = method->klass->image;
7384 method_index = mono_method_get_index (method);
7385 ca = &image->tables [MONO_TABLE_METHOD];
7387 if (method->klass->generic_class || mono_method_signature (method)->generic_param_count) {
7388 /* FIXME FIXME FIXME */
7392 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7393 if (method_index == ca->rows) {
7394 ca = &image->tables [MONO_TABLE_PARAM];
7395 param_last = ca->rows + 1;
7397 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7398 ca = &image->tables [MONO_TABLE_PARAM];
7401 for (i = param_list; i < param_last; ++i) {
7402 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7403 if (param_pos == param) {
7411 idx <<= MONO_CUSTOM_ATTR_BITS;
7412 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7413 return mono_custom_attrs_from_index (image, idx);
7417 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7421 for (i = 0; i < ainfo->num_attrs; ++i) {
7422 klass = ainfo->attrs [i].ctor->klass;
7423 if (mono_class_has_parent (klass, attr_klass))
7430 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7437 for (i = 0; i < ainfo->num_attrs; ++i) {
7438 klass = ainfo->attrs [i].ctor->klass;
7439 if (mono_class_has_parent (klass, attr_klass)) {
7444 if (attr_index == -1)
7447 attrs = mono_custom_attrs_construct (ainfo);
7449 return mono_array_get (attrs, MonoObject*, attr_index);
7455 * mono_reflection_get_custom_attrs_info:
7456 * @obj: a reflection object handle
7458 * Return the custom attribute info for attributes defined for the
7459 * reflection handle @obj. The objects.
7462 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7465 MonoCustomAttrInfo *cinfo = NULL;
7467 klass = obj->vtable->klass;
7468 if (klass == mono_defaults.monotype_class) {
7469 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7470 klass = mono_class_from_mono_type (rtype->type);
7471 cinfo = mono_custom_attrs_from_class (klass);
7472 } else if (strcmp ("Assembly", klass->name) == 0) {
7473 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7474 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7475 } else if (strcmp ("Module", klass->name) == 0) {
7476 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7477 cinfo = mono_custom_attrs_from_module (module->image);
7478 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7479 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7480 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7481 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7482 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7483 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7484 } else if (strcmp ("MonoField", klass->name) == 0) {
7485 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7486 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7487 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7488 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7489 cinfo = mono_custom_attrs_from_method (rmethod->method);
7490 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7491 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7492 cinfo = mono_custom_attrs_from_method (method);
7493 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7494 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7495 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7496 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7497 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7498 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7499 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7500 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7501 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7502 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7503 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7504 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7505 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7506 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7507 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7508 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7509 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7510 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7511 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7512 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7513 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7514 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7515 } else { /* handle other types here... */
7516 g_error ("get custom attrs not yet supported for %s", klass->name);
7523 * mono_reflection_get_custom_attrs_by_type:
7524 * @obj: a reflection object handle
7526 * Return an array with all the custom attributes defined of the
7527 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7528 * of that type are returned. The objects are fully build.
7531 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7534 MonoCustomAttrInfo *cinfo;
7536 cinfo = mono_reflection_get_custom_attrs_info (obj);
7539 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7541 result = mono_custom_attrs_construct (cinfo);
7543 mono_custom_attrs_free (cinfo);
7546 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7547 result = mono_array_new (mono_domain_get (), klass, 0);
7554 * mono_reflection_get_custom_attrs:
7555 * @obj: a reflection object handle
7557 * Return an array with all the custom attributes defined of the
7558 * reflection handle @obj. The objects are fully build.
7561 mono_reflection_get_custom_attrs (MonoObject *obj)
7563 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7567 * mono_reflection_get_custom_attrs_data:
7568 * @obj: a reflection obj handle
7570 * Returns an array of System.Reflection.CustomAttributeData,
7571 * which include information about attributes reflected on
7572 * types loaded using the Reflection Only methods
7575 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7578 MonoCustomAttrInfo *cinfo;
7580 cinfo = mono_reflection_get_custom_attrs_info (obj);
7582 result = mono_custom_attrs_data_construct (cinfo);
7584 mono_custom_attrs_free (cinfo);
7587 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7588 result = mono_array_new (mono_domain_get (), klass, 0);
7595 * LOCKING: Assumes the loader lock is held.
7597 static MonoMethodSignature*
7598 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7599 MonoMethodSignature *sig;
7602 count = parameters? mono_array_length (parameters): 0;
7604 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7605 sig->param_count = count;
7606 sig->sentinelpos = -1; /* FIXME */
7607 for (i = 0; i < count; ++i) {
7608 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7609 sig->params [i] = pt->type;
7615 * LOCKING: Assumes the loader lock is held.
7617 static MonoMethodSignature*
7618 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7619 MonoMethodSignature *sig;
7621 sig = parameters_to_signature (mp, ctor->parameters);
7622 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7623 sig->ret = &mono_defaults.void_class->byval_arg;
7628 * LOCKING: Assumes the loader lock is held.
7630 static MonoMethodSignature*
7631 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7632 MonoMethodSignature *sig;
7634 sig = parameters_to_signature (mp, method->parameters);
7635 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7636 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7637 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7641 static MonoMethodSignature*
7642 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7643 MonoMethodSignature *sig;
7645 sig = parameters_to_signature (NULL, method->parameters);
7646 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7647 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7648 sig->generic_param_count = 0;
7653 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7655 MonoClass *klass = mono_object_class (prop);
7656 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7657 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7658 *name = mono_string_to_utf8 (pb->name);
7659 *type = pb->type->type;
7661 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7662 *name = g_strdup (p->property->name);
7663 if (p->property->get)
7664 *type = mono_method_signature (p->property->get)->ret;
7666 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7671 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7673 MonoClass *klass = mono_object_class (field);
7674 if (strcmp (klass->name, "FieldBuilder") == 0) {
7675 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7676 *name = mono_string_to_utf8 (fb->name);
7677 *type = fb->type->type;
7679 MonoReflectionField *f = (MonoReflectionField *)field;
7680 *name = g_strdup (f->field->name);
7681 *type = f->field->type;
7686 * Encode a value in a custom attribute stream of bytes.
7687 * The value to encode is either supplied as an object in argument val
7688 * (valuetypes are boxed), or as a pointer to the data in the
7690 * @type represents the type of the value
7691 * @buffer is the start of the buffer
7692 * @p the current position in the buffer
7693 * @buflen contains the size of the buffer and is used to return the new buffer size
7694 * if this needs to be realloced.
7695 * @retbuffer and @retp return the start and the position of the buffer
7698 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7700 MonoTypeEnum simple_type;
7702 if ((p-buffer) + 10 >= *buflen) {
7705 newbuf = g_realloc (buffer, *buflen);
7706 p = newbuf + (p-buffer);
7710 argval = ((char*)arg + sizeof (MonoObject));
7711 simple_type = type->type;
7713 switch (simple_type) {
7714 case MONO_TYPE_BOOLEAN:
7719 case MONO_TYPE_CHAR:
7722 swap_with_size (p, argval, 2, 1);
7728 swap_with_size (p, argval, 4, 1);
7734 swap_with_size (p, argval, 8, 1);
7737 case MONO_TYPE_VALUETYPE:
7738 if (type->data.klass->enumtype) {
7739 simple_type = type->data.klass->enum_basetype->type;
7742 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7745 case MONO_TYPE_STRING: {
7752 str = mono_string_to_utf8 ((MonoString*)arg);
7753 slen = strlen (str);
7754 if ((p-buffer) + 10 + slen >= *buflen) {
7758 newbuf = g_realloc (buffer, *buflen);
7759 p = newbuf + (p-buffer);
7762 mono_metadata_encode_value (slen, p, &p);
7763 memcpy (p, str, slen);
7768 case MONO_TYPE_CLASS: {
7776 k = mono_object_class (arg);
7777 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7778 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7779 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7781 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7782 slen = strlen (str);
7783 if ((p-buffer) + 10 + slen >= *buflen) {
7787 newbuf = g_realloc (buffer, *buflen);
7788 p = newbuf + (p-buffer);
7791 mono_metadata_encode_value (slen, p, &p);
7792 memcpy (p, str, slen);
7797 case MONO_TYPE_SZARRAY: {
7799 MonoClass *eclass, *arg_eclass;
7802 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7805 len = mono_array_length ((MonoArray*)arg);
7807 *p++ = (len >> 8) & 0xff;
7808 *p++ = (len >> 16) & 0xff;
7809 *p++ = (len >> 24) & 0xff;
7811 *retbuffer = buffer;
7812 eclass = type->data.klass;
7813 arg_eclass = mono_object_class (arg)->element_class;
7816 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7817 eclass = mono_defaults.object_class;
7819 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7820 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7821 int elsize = mono_class_array_element_size (arg_eclass);
7822 for (i = 0; i < len; ++i) {
7823 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7826 } else if (eclass->valuetype && arg_eclass->valuetype) {
7827 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7828 int elsize = mono_class_array_element_size (eclass);
7829 for (i = 0; i < len; ++i) {
7830 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7834 for (i = 0; i < len; ++i) {
7835 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7840 case MONO_TYPE_OBJECT: {
7846 * The parameter type is 'object' but the type of the actual
7847 * argument is not. So we have to add type information to the blob
7848 * too. This is completely undocumented in the spec.
7852 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7857 klass = mono_object_class (arg);
7859 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7862 } else if (klass->enumtype) {
7864 } else if (klass == mono_defaults.string_class) {
7865 simple_type = MONO_TYPE_STRING;
7868 } else if (klass->rank == 1) {
7869 simple_type = MONO_TYPE_SZARRAY;
7871 *p++ = klass->element_class->byval_arg.type;
7873 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7874 *p++ = simple_type = klass->byval_arg.type;
7877 g_error ("unhandled type in custom attr");
7879 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7880 slen = strlen (str);
7881 if ((p-buffer) + 10 + slen >= *buflen) {
7885 newbuf = g_realloc (buffer, *buflen);
7886 p = newbuf + (p-buffer);
7889 mono_metadata_encode_value (slen, p, &p);
7890 memcpy (p, str, slen);
7893 simple_type = klass->enum_basetype->type;
7897 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7900 *retbuffer = buffer;
7904 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7907 /* Preallocate a large enough buffer */
7908 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7909 char *str = type_get_qualified_name (type, NULL);
7915 len += strlen (name);
7917 if ((p-buffer) + 20 + len >= *buflen) {
7921 newbuf = g_realloc (buffer, *buflen);
7922 p = newbuf + (p-buffer);
7926 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7927 char *str = type_get_qualified_name (type, NULL);
7928 int slen = strlen (str);
7932 * This seems to be optional...
7935 mono_metadata_encode_value (slen, p, &p);
7936 memcpy (p, str, slen);
7939 } else if (type->type == MONO_TYPE_OBJECT) {
7941 } else if (type->type == MONO_TYPE_CLASS) {
7942 /* it should be a type: encode_cattr_value () has the check */
7945 mono_metadata_encode_value (type->type, p, &p);
7946 if (type->type == MONO_TYPE_SZARRAY)
7947 mono_metadata_encode_value (type->data.klass->this_arg.type, p, &p);
7949 len = strlen (name);
7950 mono_metadata_encode_value (len, p, &p);
7951 memcpy (p, name, len);
7953 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7955 *retbuffer = buffer;
7959 * mono_reflection_get_custom_attrs_blob:
7960 * @ctor: custom attribute constructor
7961 * @ctorArgs: arguments o the constructor
7967 * Creates the blob of data that needs to be saved in the metadata and that represents
7968 * the custom attributed described by @ctor, @ctorArgs etc.
7969 * Returns: a Byte array representing the blob of data.
7972 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7975 MonoMethodSignature *sig;
7980 MONO_ARCH_SAVE_REGS;
7982 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7983 /* sig is freed later so allocate it in the heap */
7984 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
7986 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7989 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7991 p = buffer = g_malloc (buflen);
7992 /* write the prolog */
7995 for (i = 0; i < sig->param_count; ++i) {
7996 arg = mono_array_get (ctorArgs, MonoObject*, i);
7997 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8001 i += mono_array_length (properties);
8003 i += mono_array_length (fields);
8005 *p++ = (i >> 8) & 0xff;
8008 for (i = 0; i < mono_array_length (properties); ++i) {
8012 prop = mono_array_get (properties, gpointer, i);
8013 get_prop_name_and_type (prop, &pname, &ptype);
8014 *p++ = 0x54; /* PROPERTY signature */
8015 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8022 for (i = 0; i < mono_array_length (fields); ++i) {
8026 field = mono_array_get (fields, gpointer, i);
8027 get_field_name_and_type (field, &fname, &ftype);
8028 *p++ = 0x53; /* FIELD signature */
8029 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8034 g_assert (p - buffer <= buflen);
8035 buflen = p - buffer;
8036 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8037 p = mono_array_addr (result, char, 0);
8038 memcpy (p, buffer, buflen);
8040 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8046 static void* reflection_info_desc = NULL;
8050 * mono_reflection_setup_internal_class:
8051 * @tb: a TypeBuilder object
8053 * Creates a MonoClass that represents the TypeBuilder.
8054 * This is a trick that lets us simplify a lot of reflection code
8055 * (and will allow us to support Build and Run assemblies easier).
8058 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8060 MonoClass *klass, *parent;
8062 MONO_ARCH_SAVE_REGS;
8064 mono_loader_lock ();
8067 /* check so we can compile corlib correctly */
8068 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8069 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8070 parent = tb->parent->type->data.klass;
8072 parent = my_mono_class_from_mono_type (tb->parent->type);
8078 /* the type has already being created: it means we just have to change the parent */
8079 if (tb->type.type) {
8080 klass = mono_class_from_mono_type (tb->type.type);
8081 klass->parent = NULL;
8082 /* fool mono_class_setup_parent */
8083 klass->supertypes = NULL;
8084 mono_class_setup_parent (klass, parent);
8085 mono_class_setup_mono_type (klass);
8086 mono_loader_unlock ();
8090 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8092 klass->image = &tb->module->dynamic_image->image;
8094 klass->inited = 1; /* we lie to the runtime */
8095 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8096 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8097 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8098 klass->flags = tb->attrs;
8100 klass->element_class = klass;
8103 if (!reflection_info_desc) {
8105 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);
8107 mono_gc_register_root (&klass->reflection_info, sizeof (gpointer), reflection_info_desc);
8109 klass->reflection_info = tb;
8111 /* Put into cache so mono_class_get () will find it */
8112 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8114 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8115 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8117 if (parent != NULL) {
8118 mono_class_setup_parent (klass, parent);
8119 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8120 const char *old_n = klass->name;
8121 /* trick to get relative numbering right when compiling corlib */
8122 klass->name = "BuildingObject";
8123 mono_class_setup_parent (klass, mono_defaults.object_class);
8124 klass->name = old_n;
8127 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8128 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8129 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8130 klass->instance_size = sizeof (MonoObject);
8131 klass->size_inited = 1;
8132 mono_class_setup_vtable_general (klass, NULL, 0);
8135 mono_class_setup_mono_type (klass);
8137 mono_class_setup_supertypes (klass);
8140 * FIXME: handle interfaces.
8143 tb->type.type = &klass->byval_arg;
8145 if (tb->nesting_type) {
8146 g_assert (tb->nesting_type->type);
8147 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8150 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8152 mono_loader_unlock ();
8156 * mono_reflection_setup_generic_class:
8157 * @tb: a TypeBuilder object
8159 * Setup the generic class before adding the first generic parameter.
8162 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8166 MONO_ARCH_SAVE_REGS;
8168 klass = my_mono_class_from_mono_type (tb->type.type);
8169 if (tb->generic_container)
8172 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8173 tb->generic_container->klass = klass;
8175 tb->generic_container->context.container = tb->generic_container;
8179 * mono_reflection_create_generic_class:
8180 * @tb: a TypeBuilder object
8182 * Creates the generic class after all generic parameters have been added.
8185 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8190 MONO_ARCH_SAVE_REGS;
8192 klass = my_mono_class_from_mono_type (tb->type.type);
8194 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8196 if (klass->generic_container || (count == 0))
8199 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
8201 klass->generic_container = tb->generic_container;
8203 klass->generic_container->type_argc = count;
8204 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8206 for (i = 0; i < count; i++) {
8207 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8208 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8209 g_assert (klass->generic_container->type_params [i].owner);
8212 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
8216 * mono_reflection_create_internal_class:
8217 * @tb: a TypeBuilder object
8219 * Actually create the MonoClass that is associated with the TypeBuilder.
8222 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8226 MONO_ARCH_SAVE_REGS;
8228 klass = my_mono_class_from_mono_type (tb->type.type);
8230 mono_loader_lock ();
8231 if (klass->enumtype && klass->enum_basetype == NULL) {
8232 MonoReflectionFieldBuilder *fb;
8235 g_assert (tb->fields != NULL);
8236 g_assert (mono_array_length (tb->fields) >= 1);
8238 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8240 klass->enum_basetype = fb->type->type;
8241 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8242 if (!klass->element_class)
8243 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8246 * get the element_class from the current corlib.
8248 ec = default_class_from_mono_type (klass->enum_basetype);
8249 klass->instance_size = ec->instance_size;
8250 klass->size_inited = 1;
8252 * this is almost safe to do with enums and it's needed to be able
8253 * to create objects of the enum type (for use in SetConstant).
8255 /* FIXME: Does this mean enums can't have method overrides ? */
8256 mono_class_setup_vtable_general (klass, NULL, 0);
8258 mono_loader_unlock ();
8261 static MonoMarshalSpec*
8262 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8263 MonoReflectionMarshal *minfo)
8265 MonoMarshalSpec *res;
8267 res = g_new0 (MonoMarshalSpec, 1);
8268 res->native = minfo->type;
8270 switch (minfo->type) {
8271 case MONO_NATIVE_LPARRAY:
8272 res->data.array_data.elem_type = minfo->eltype;
8273 if (minfo->has_size) {
8274 res->data.array_data.param_num = minfo->param_num;
8275 res->data.array_data.num_elem = minfo->count;
8276 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8279 res->data.array_data.param_num = -1;
8280 res->data.array_data.num_elem = -1;
8281 res->data.array_data.elem_mult = -1;
8285 case MONO_NATIVE_BYVALTSTR:
8286 case MONO_NATIVE_BYVALARRAY:
8287 res->data.array_data.num_elem = minfo->count;
8290 case MONO_NATIVE_CUSTOM:
8291 if (minfo->marshaltyperef)
8292 res->data.custom_data.custom_name =
8293 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8295 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8305 MonoReflectionMarshal*
8306 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8307 MonoMarshalSpec *spec)
8309 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8310 MonoReflectionMarshal *minfo;
8313 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8314 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8315 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8316 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8319 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8320 minfo->type = spec->native;
8322 switch (minfo->type) {
8323 case MONO_NATIVE_LPARRAY:
8324 minfo->eltype = spec->data.array_data.elem_type;
8325 minfo->count = spec->data.array_data.num_elem;
8326 minfo->param_num = spec->data.array_data.param_num;
8329 case MONO_NATIVE_BYVALTSTR:
8330 case MONO_NATIVE_BYVALARRAY:
8331 minfo->count = spec->data.array_data.num_elem;
8334 case MONO_NATIVE_CUSTOM:
8335 if (spec->data.custom_data.custom_name) {
8336 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8338 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8340 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8342 if (spec->data.custom_data.cookie)
8343 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8354 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8355 ReflectionMethodBuilder *rmb,
8356 MonoMethodSignature *sig)
8359 MonoMethodNormal *pm;
8360 MonoMarshalSpec **specs;
8361 MonoReflectionMethodAux *method_aux;
8366 g_assert (!klass->generic_class);
8369 * Methods created using a MethodBuilder should have their memory allocated
8370 * inside the image mempool, while dynamic methods should have their memory
8373 dynamic = rmb->refs != NULL;
8374 mp = dynamic ? NULL : klass->image->mempool;
8376 mono_loader_lock ();
8378 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8379 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8380 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8382 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8384 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8386 pm = (MonoMethodNormal*)m;
8389 m->flags = rmb->attrs;
8390 m->iflags = rmb->iattrs;
8391 m->name = dynamic ? mono_string_to_utf8 (rmb->name) : mono_string_to_utf8_mp (mp, rmb->name);
8395 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8397 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8398 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8401 m->signature->pinvoke = 1;
8402 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8403 m->signature->pinvoke = 1;
8405 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8407 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8408 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8410 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8412 if (klass->image->dynamic)
8413 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8415 mono_loader_unlock ();
8418 } else if (!m->klass->dummy &&
8419 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8420 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8421 MonoMethodHeader *header;
8423 gint32 max_stack, i;
8424 gint32 num_locals = 0;
8425 gint32 num_clauses = 0;
8429 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8430 code_size = rmb->ilgen->code_len;
8431 max_stack = rmb->ilgen->max_stack;
8432 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8433 if (rmb->ilgen->ex_handlers)
8434 num_clauses = method_count_clauses (rmb->ilgen);
8437 code = mono_array_addr (rmb->code, guint8, 0);
8438 code_size = mono_array_length (rmb->code);
8439 /* we probably need to run a verifier on the code... */
8449 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8450 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8451 header->code_size = code_size;
8452 header->code = mp_g_malloc (mp, code_size);
8453 memcpy ((char*)header->code, code, code_size);
8454 header->max_stack = max_stack;
8455 header->init_locals = rmb->init_locals;
8456 header->num_locals = num_locals;
8458 for (i = 0; i < num_locals; ++i) {
8459 MonoReflectionLocalBuilder *lb =
8460 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8462 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8463 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8466 header->num_clauses = num_clauses;
8468 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8469 rmb->ilgen, num_clauses);
8472 pm->header = header;
8475 if (rmb->generic_params) {
8476 int count = mono_array_length (rmb->generic_params);
8477 MonoGenericContainer *container;
8478 MonoGenericContext *context;
8480 m->generic_container = container = rmb->generic_container;
8481 container->type_argc = count;
8482 container->type_params = g_new0 (MonoGenericParam, count);
8484 for (i = 0; i < count; i++) {
8485 MonoReflectionGenericParam *gp =
8486 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8488 container->type_params [i] = *gp->type.type->data.generic_param;
8489 container->type_params [i].method = m;
8492 context = &container->context;
8493 context->container = container;
8494 if (klass->generic_container) {
8495 container->parent = klass->generic_container;
8496 context->gclass = klass->generic_container->context.gclass;
8498 context->gmethod = mono_get_shared_generic_method (container);
8502 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8506 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8508 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8509 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8510 for (i = 0; i < rmb->nrefs; ++i)
8511 data [i + 1] = rmb->refs [i];
8516 /* Parameter info */
8519 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8520 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8521 for (i = 0; i <= m->signature->param_count; ++i) {
8522 MonoReflectionParamBuilder *pb;
8523 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8524 if ((i > 0) && (pb->attrs)) {
8525 /* Make a copy since it might point to a shared type structure */
8526 /* FIXME: Alloc this from a mempool */
8527 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)));
8528 m->signature->params [i - 1]->attrs = pb->attrs;
8531 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8532 MonoDynamicImage *assembly;
8533 guint32 idx, def_type, len;
8537 if (!method_aux->param_defaults) {
8538 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8539 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8541 assembly = (MonoDynamicImage*)klass->image;
8542 idx = encode_constant (assembly, pb->def_value, &def_type);
8543 /* Copy the data from the blob since it might get realloc-ed */
8544 p = assembly->blob.data + idx;
8545 len = mono_metadata_decode_blob_size (p, &p2);
8547 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8548 method_aux->param_default_types [i] = def_type;
8549 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8553 method_aux->param_names [i] = dynamic ? mono_string_to_utf8 (pb->name) : mono_string_to_utf8_mp (mp, pb->name);
8555 if (!method_aux->param_cattr)
8556 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8557 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8563 /* Parameter marshalling */
8566 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8567 MonoReflectionParamBuilder *pb;
8568 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8569 if (pb->marshal_info) {
8571 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8572 specs [pb->position] =
8573 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8577 if (specs != NULL) {
8579 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8580 method_aux->param_marshall = specs;
8583 if (klass->image->dynamic && method_aux)
8584 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8586 mono_loader_unlock ();
8592 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8594 ReflectionMethodBuilder rmb;
8595 MonoMethodSignature *sig;
8597 mono_loader_lock ();
8598 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8599 mono_loader_unlock ();
8601 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8603 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8604 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8606 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8607 /* ilgen is no longer needed */
8615 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8617 ReflectionMethodBuilder rmb;
8618 MonoMethodSignature *sig;
8620 mono_loader_lock ();
8621 sig = method_builder_to_signature (klass->image->mempool, mb);
8622 mono_loader_unlock ();
8624 reflection_methodbuilder_from_method_builder (&rmb, mb);
8626 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8627 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8629 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8630 /* ilgen is no longer needed */
8636 static MonoClassField*
8637 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8639 MonoClassField *field;
8643 field = g_new0 (MonoClassField, 1);
8645 field->name = mono_string_to_utf8 (fb->name);
8647 /* FIXME: handle type modifiers */
8648 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8649 field->type->attrs = fb->attrs;
8651 field->type = fb->type->type;
8653 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8654 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8655 if (fb->offset != -1)
8656 field->offset = fb->offset;
8657 field->parent = klass;
8658 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8660 if (fb->def_value) {
8661 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8662 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8663 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8664 /* Copy the data from the blob since it might get realloc-ed */
8665 p = assembly->blob.data + idx;
8666 len = mono_metadata_decode_blob_size (p, &p2);
8668 field->data = g_malloc (len);
8669 memcpy ((gpointer)field->data, p, len);
8676 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8679 MonoReflectionTypeBuilder *tb = NULL;
8680 MonoGenericClass *gclass, *cached;
8681 MonoInflatedGenericClass *igclass;
8682 MonoDynamicGenericClass *dgclass = NULL;
8683 gboolean is_dynamic = FALSE;
8688 klass = mono_class_from_mono_type (type->type);
8689 if (!klass->generic_container && !klass->generic_class &&
8690 !(klass->nested_in && klass->nested_in->generic_container))
8693 mono_loader_lock ();
8695 domain = mono_object_domain (type);
8697 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8698 tb = (MonoReflectionTypeBuilder *) type;
8701 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8702 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8703 MonoReflectionType *rgt = rgi->generic_type;
8705 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8706 tb = (MonoReflectionTypeBuilder *) rgt;
8709 } else if (klass->wastypebuilder) {
8710 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8716 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8717 igclass = &dgclass->generic_class;
8718 gclass = &igclass->generic_class;
8719 gclass->is_dynamic = TRUE;
8720 gclass->is_inflated = TRUE;
8722 igclass = g_new0 (MonoInflatedGenericClass, 1);
8723 gclass = &igclass->generic_class;
8724 gclass->is_inflated = TRUE;
8727 gclass->inst = g_new0 (MonoGenericInst, 1);
8729 gclass->inst->type_argc = type_argc;
8730 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8731 gclass->inst->is_reference = 1;
8733 for (i = 0; i < gclass->inst->type_argc; ++i) {
8734 MonoType *t = dup_type (types [i]);
8736 if (!gclass->inst->is_open)
8737 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8738 if (gclass->inst->is_reference)
8739 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8740 gclass->inst->type_argv [i] = t;
8743 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8745 gclass->container_class = klass;
8747 if (klass->generic_class) {
8748 MonoGenericClass *kgclass = klass->generic_class;
8749 MonoGenericClass *ogclass = gclass;
8751 ogclass->context = g_new0 (MonoGenericContext, 1);
8752 ogclass->context->container = gclass->container_class->generic_container;
8753 ogclass->context->gclass = gclass;
8756 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8757 igclass = &dgclass->generic_class;
8758 gclass = &igclass->generic_class;
8759 gclass->is_dynamic = TRUE;
8760 gclass->is_inflated = TRUE;
8762 igclass = g_new0 (MonoInflatedGenericClass, 1);
8763 gclass = &igclass->generic_class;
8764 gclass->is_inflated = TRUE;
8767 gclass->inst = g_new0 (MonoGenericInst, 1);
8769 gclass->inst->type_argc = kgclass->inst->type_argc;
8770 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8771 gclass->inst->is_reference = 1;
8773 for (i = 0; i < gclass->inst->type_argc; i++) {
8774 MonoType *t = kgclass->inst->type_argv [i];
8776 t = mono_class_inflate_generic_type (t, ogclass->context);
8778 if (!gclass->inst->is_open)
8779 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8780 if (gclass->inst->is_reference)
8781 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8783 gclass->inst->type_argv [i] = t;
8786 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8788 gclass->container_class = kgclass->container_class;
8791 geninst = g_new0 (MonoType, 1);
8792 geninst->type = MONO_TYPE_GENERICINST;
8794 cached = mono_metadata_lookup_generic_class (gclass);
8797 mono_loader_unlock ();
8798 geninst->data.generic_class = cached;
8802 geninst->data.generic_class = gclass;
8804 gclass->context = g_new0 (MonoGenericContext, 1);
8805 gclass->context->container = gclass->container_class->generic_container;
8806 gclass->context->gclass = gclass;
8808 mono_loader_unlock ();
8814 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8817 MonoGenericClass *gclass, *cached;
8818 MonoInflatedGenericClass *igclass;
8822 klass = mono_class_from_mono_type (type);
8823 if (!klass->generic_container && !klass->generic_class &&
8824 !(klass->nested_in && klass->nested_in->generic_container))
8827 mono_loader_lock ();
8829 igclass = g_new0 (MonoInflatedGenericClass, 1);
8830 gclass = &igclass->generic_class;
8831 gclass->is_inflated = TRUE;
8833 gclass->inst = g_new0 (MonoGenericInst, 1);
8834 gclass->inst->type_argc = type_argc;
8835 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8836 gclass->inst->is_reference = 1;
8838 for (i = 0; i < gclass->inst->type_argc; ++i) {
8839 MonoType *t = dup_type (types [i]);
8841 if (!gclass->inst->is_open)
8842 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8843 if (gclass->inst->is_reference)
8844 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8846 gclass->inst->type_argv [i] = t;
8849 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8851 gclass->container_class = klass;
8853 if (klass->generic_class) {
8854 MonoGenericClass *kgclass = klass->generic_class;
8855 MonoGenericClass *ogclass = gclass;
8857 gclass->context = g_new0 (MonoGenericContext, 1);
8858 gclass->context->container = gclass->container_class->generic_container;
8859 gclass->context->gclass = gclass;
8861 igclass = g_new0 (MonoInflatedGenericClass, 1);
8862 gclass = &igclass->generic_class;
8863 gclass->is_inflated = TRUE;
8865 gclass->inst = g_new0 (MonoGenericInst, 1);
8866 gclass->inst->type_argc = kgclass->inst->type_argc;
8867 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8868 gclass->inst->is_reference = 1;
8870 for (i = 0; i < gclass->inst->type_argc; i++) {
8871 MonoType *t = kgclass->inst->type_argv [i];
8873 t = mono_class_inflate_generic_type (t, ogclass->context);
8875 if (!gclass->inst->is_open)
8876 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8877 if (gclass->inst->is_reference)
8878 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8880 gclass->inst->type_argv [i] = t;
8883 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8885 gclass->container_class = kgclass->container_class;
8888 geninst = g_new0 (MonoType, 1);
8889 geninst->type = MONO_TYPE_GENERICINST;
8891 cached = mono_metadata_lookup_generic_class (gclass);
8894 mono_loader_unlock ();
8895 geninst->data.generic_class = cached;
8899 geninst->data.generic_class = gclass;
8901 gclass->context = g_new0 (MonoGenericContext, 1);
8902 gclass->context->container = gclass->container_class->generic_container;
8903 gclass->context->gclass = gclass;
8905 mono_loader_unlock ();
8910 static inline MonoType*
8911 dup_type (const MonoType *original)
8913 MonoType *r = g_new0 (MonoType, 1);
8915 r->attrs = original->attrs;
8916 r->byref = original->byref;
8917 if (original->type == MONO_TYPE_PTR)
8918 r->data.type = dup_type (original->data.type);
8919 else if (original->type == MONO_TYPE_ARRAY)
8920 r->data.array = mono_dup_array_type (original->data.array);
8921 else if (original->type == MONO_TYPE_FNPTR)
8922 r->data.method = mono_metadata_signature_deep_dup (original->data.method);
8923 mono_stats.generics_metadata_size += sizeof (MonoType);
8927 MonoReflectionMethod*
8928 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8930 MonoMethod *method, *inflated;
8931 MonoReflectionMethodBuilder *mb = NULL;
8932 MonoGenericContainer *container;
8933 MonoGenericMethod *gmethod;
8934 MonoGenericContext *context;
8935 MonoGenericInst *ginst;
8938 MONO_ARCH_SAVE_REGS;
8939 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8940 MonoReflectionTypeBuilder *tb;
8943 mb = (MonoReflectionMethodBuilder *) rmethod;
8944 tb = (MonoReflectionTypeBuilder *) mb->type;
8945 klass = mono_class_from_mono_type (tb->type.type);
8947 method = methodbuilder_to_mono_method (klass, mb);
8949 method = rmethod->method;
8952 method = mono_get_inflated_method (method);
8954 count = mono_method_signature (method)->generic_param_count;
8955 if (count != mono_array_length (types))
8958 container = method->generic_container;
8959 g_assert (container);
8961 if (!container->method_hash)
8962 container->method_hash = g_hash_table_new (
8963 (GHashFunc) mono_metadata_generic_method_hash,
8964 (GCompareFunc) mono_metadata_generic_method_equal);
8966 ginst = g_new0 (MonoGenericInst,1 );
8967 ginst->type_argc = count;
8968 ginst->type_argv = g_new0 (MonoType *, count);
8969 ginst->is_reference = 1;
8970 for (i = 0; i < count; i++) {
8971 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8972 ginst->type_argv [i] = dup_type (garg->type);
8974 if (!ginst->is_open)
8975 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8976 if (ginst->is_reference)
8977 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8979 ginst = mono_metadata_lookup_generic_inst (ginst);
8981 gmethod = g_new0 (MonoGenericMethod, 1);
8982 gmethod->generic_class = method->klass->generic_class;
8983 gmethod->container = container;
8984 gmethod->inst = ginst;
8986 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8990 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8993 gmethod->reflection_info = rmethod;
8995 context = g_new0 (MonoGenericContext, 1);
8996 context->container = container;
8997 context->gclass = method->klass->generic_class;
8998 context->gmethod = gmethod;
9000 if (method->is_inflated)
9001 method = ((MonoMethodInflated *) method)->declaring;
9003 inflated = mono_class_inflate_generic_method (method, context);
9004 g_hash_table_insert (container->method_hash, gmethod, inflated);
9006 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9010 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
9012 MonoGenericMethod *gmethod = NULL;
9013 MonoInflatedGenericClass *gclass;
9014 MonoGenericContext *context;
9018 klass = mono_class_from_mono_type (type->type.type);
9019 gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
9020 n = mono_method_signature (method)->generic_param_count;
9022 context = gclass->generic_class.context;
9023 g_assert (context && context->container);
9025 gmethod = g_new0 (MonoGenericMethod, 1);
9026 gmethod->generic_class = &gclass->generic_class;
9027 gmethod->container = method->generic_container;
9028 gmethod->reflection_info = obj;
9030 gmethod->inst = g_new0 (MonoGenericInst, 1);
9031 gmethod->inst->type_argc = n;
9032 gmethod->inst->type_argv = g_new0 (MonoType *, n);
9034 for (i = 0; i < n; i++) {
9035 MonoGenericParam *gparam = &method->generic_container->type_params [i];
9036 g_assert (gparam->pklass);
9037 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
9040 g_assert (gmethod->container->parent == context->container);
9042 context = g_new0 (MonoGenericContext, 1);
9043 context->container = gmethod->container;
9044 context->gclass = &gclass->generic_class;
9045 context->gmethod = gmethod;
9048 return mono_class_inflate_generic_method (method, context);
9052 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9057 gklass = mono_class_from_mono_type (type->generic_type->type);
9059 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9060 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9061 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9062 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9063 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9064 method = ((MonoReflectionMethod *) obj)->method;
9066 method = NULL; /* prevent compiler warning */
9067 g_assert_not_reached ();
9070 return inflate_mono_method (type, method, obj);
9074 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9075 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9078 MonoGenericClass *gclass;
9079 MonoDynamicGenericClass *dgclass;
9080 MonoClass *klass, *gklass;
9083 MONO_ARCH_SAVE_REGS;
9085 klass = mono_class_from_mono_type (type->type.type);
9086 gclass = type->type.type->data.generic_class;
9088 g_assert (gclass->is_dynamic);
9089 dgclass = (MonoDynamicGenericClass *) gclass;
9091 if (dgclass->initialized)
9094 gklass = gclass->container_class;
9095 mono_class_init (gklass);
9097 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9098 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9099 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9100 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9101 dgclass->count_events = events ? mono_array_length (events) : 0;
9103 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9104 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9105 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9106 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9107 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9109 for (i = 0; i < dgclass->count_methods; i++) {
9110 MonoObject *obj = mono_array_get (methods, gpointer, i);
9112 dgclass->methods [i] = inflate_method (type, obj);
9115 for (i = 0; i < dgclass->count_ctors; i++) {
9116 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9118 dgclass->ctors [i] = inflate_method (type, obj);
9121 for (i = 0; i < dgclass->count_fields; i++) {
9122 MonoObject *obj = mono_array_get (fields, gpointer, i);
9123 MonoClassField *field;
9124 MonoInflatedField *ifield;
9126 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9127 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9128 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9129 field = ((MonoReflectionField *) obj)->field;
9131 field = NULL; /* prevent compiler warning */
9132 g_assert_not_reached ();
9135 ifield = g_new0 (MonoInflatedField, 1);
9136 ifield->generic_type = field->type;
9137 ifield->reflection_info = obj;
9139 dgclass->fields [i] = *field;
9140 dgclass->fields [i].parent = klass;
9141 dgclass->fields [i].generic_info = ifield;
9142 dgclass->fields [i].type = mono_class_inflate_generic_type (
9143 field->type, dgclass->generic_class.generic_class.context);
9146 for (i = 0; i < dgclass->count_properties; i++) {
9147 MonoObject *obj = mono_array_get (properties, gpointer, i);
9148 MonoProperty *property = &dgclass->properties [i];
9150 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9151 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9153 property->parent = klass;
9154 property->attrs = pb->attrs;
9155 property->name = mono_string_to_utf8 (pb->name);
9157 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9159 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9160 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9161 *property = *((MonoReflectionProperty *) obj)->property;
9164 property->get = inflate_mono_method (type, property->get, NULL);
9166 property->set = inflate_mono_method (type, property->set, NULL);
9168 g_assert_not_reached ();
9171 for (i = 0; i < dgclass->count_events; i++) {
9172 MonoObject *obj = mono_array_get (events, gpointer, i);
9173 MonoEvent *event = &dgclass->events [i];
9175 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9176 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9178 event->parent = klass;
9179 event->attrs = eb->attrs;
9180 event->name = mono_string_to_utf8 (eb->name);
9182 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9183 if (eb->remove_method)
9184 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9185 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9186 *event = *((MonoReflectionEvent *) obj)->event;
9189 event->add = inflate_mono_method (type, event->add, NULL);
9191 event->remove = inflate_mono_method (type, event->remove, NULL);
9193 g_assert_not_reached ();
9196 dgclass->initialized = TRUE;
9200 ensure_runtime_vtable (MonoClass *klass)
9202 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9205 if (!tb || klass->wastypebuilder)
9208 ensure_runtime_vtable (klass->parent);
9210 num = tb->ctors? mono_array_length (tb->ctors): 0;
9211 num += tb->num_methods;
9212 klass->method.count = num;
9213 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9214 num = tb->ctors? mono_array_length (tb->ctors): 0;
9215 for (i = 0; i < num; ++i)
9216 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9217 num = tb->num_methods;
9219 for (i = 0; i < num; ++i)
9220 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9222 if (tb->interfaces) {
9223 klass->interface_count = mono_array_length (tb->interfaces);
9224 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9225 for (i = 0; i < klass->interface_count; ++i) {
9226 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9227 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9231 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9232 for (i = 0; i < klass->method.count; ++i)
9233 klass->methods [i]->slot = i;
9235 mono_class_setup_interface_offsets (klass);
9239 * The generic vtable is needed even if image->run is not set since some
9240 * runtime code like ves_icall_Type_GetMethodsByName depends on
9241 * method->slot being defined.
9245 * tb->methods could not be freed since it is used for determining
9246 * overrides during dynamic vtable construction.
9251 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9253 MonoReflectionTypeBuilder *tb;
9259 g_assert (klass->image->dynamic);
9261 if (!klass->reflection_info)
9264 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9266 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9270 for (i = 0; i < tb->num_methods; ++i) {
9271 MonoReflectionMethodBuilder *mb =
9272 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9273 if (mb->override_method)
9279 *overrides = g_new0 (MonoMethod*, onum * 2);
9282 for (i = 0; i < tb->num_methods; ++i) {
9283 MonoReflectionMethodBuilder *mb =
9284 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9285 if (mb->override_method) {
9286 (*overrides) [onum * 2] =
9287 mb->override_method->method;
9288 (*overrides) [onum * 2 + 1] =
9291 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9292 g_assert (mb->override_method->method);
9293 g_assert (mb->mhandle);
9300 *num_overrides = onum;
9304 typebuilder_setup_fields (MonoClass *klass)
9306 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9307 MonoReflectionFieldBuilder *fb;
9308 MonoClassField *field;
9313 klass->field.count = tb->num_fields;
9314 klass->field.first = 0;
9316 if (!klass->field.count)
9319 klass->fields = g_new0 (MonoClassField, klass->field.count);
9321 for (i = 0; i < klass->field.count; ++i) {
9322 fb = mono_array_get (tb->fields, gpointer, i);
9323 field = &klass->fields [i];
9324 field->name = mono_string_to_utf8 (fb->name);
9326 /* FIXME: handle type modifiers */
9327 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9328 field->type->attrs = fb->attrs;
9330 field->type = fb->type->type;
9332 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9333 field->data = mono_array_addr (fb->rva_data, char, 0);
9334 if (fb->offset != -1)
9335 field->offset = fb->offset;
9336 field->parent = klass;
9338 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9340 if (fb->def_value) {
9341 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9342 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9343 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9344 /* Copy the data from the blob since it might get realloc-ed */
9345 p = assembly->blob.data + idx;
9346 len = mono_metadata_decode_blob_size (p, &p2);
9348 field->data = g_malloc (len);
9349 memcpy ((gpointer)field->data, p, len);
9352 mono_class_layout_fields (klass);
9356 typebuilder_setup_properties (MonoClass *klass)
9358 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9359 MonoReflectionPropertyBuilder *pb;
9362 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9363 klass->property.first = 0;
9365 klass->properties = g_new0 (MonoProperty, klass->property.count);
9366 for (i = 0; i < klass->property.count; ++i) {
9367 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9368 klass->properties [i].parent = klass;
9369 klass->properties [i].attrs = pb->attrs;
9370 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9372 klass->properties [i].get = pb->get_method->mhandle;
9374 klass->properties [i].set = pb->set_method->mhandle;
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 unamanged 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;
9804 g_print (obj->vtable->klass->name);
9805 g_assert_not_reached ();
9811 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9812 const static guint32 declsec_flags_map[] = {
9813 0x00000000, /* empty */
9814 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9815 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9816 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9817 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9818 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9819 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9820 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9821 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9822 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9823 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9824 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9825 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9826 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9827 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9828 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9829 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9830 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9831 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9835 * Returns flags that includes all available security action associated to the handle.
9836 * @token: metadata token (either for a class or a method)
9837 * @image: image where resides the metadata.
9840 mono_declsec_get_flags (MonoImage *image, guint32 token)
9842 guint32 index = mono_metadata_declsec_from_index (image, token);
9843 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9848 for (i = index; i < t->rows; i++) {
9849 guint32 cols [MONO_DECL_SECURITY_SIZE];
9851 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9852 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9855 action = cols [MONO_DECL_SECURITY_ACTION];
9856 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9857 result |= declsec_flags_map [action];
9859 g_assert_not_reached ();
9866 * Get the security actions (in the form of flags) associated with the specified method.
9868 * @method: The method for which we want the declarative security flags.
9869 * Return the declarative security flags for the method (only).
9871 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9872 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9875 mono_declsec_flags_from_method (MonoMethod *method)
9877 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9878 /* FIXME: No cache (for the moment) */
9879 guint32 idx = mono_method_get_index (method);
9880 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9881 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9882 return mono_declsec_get_flags (method->klass->image, idx);
9888 * Get the security actions (in the form of flags) associated with the specified class.
9890 * @klass: The class for which we want the declarative security flags.
9891 * Return the declarative security flags for the class.
9893 * Note: We cache the flags inside the MonoClass structure as this will get
9894 * called very often (at least for each method).
9897 mono_declsec_flags_from_class (MonoClass *klass)
9899 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9900 if (!klass->declsec_flags) {
9901 guint32 idx = mono_metadata_token_index (klass->type_token);
9902 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9903 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9904 /* we cache the flags on classes */
9905 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9907 return klass->declsec_flags;
9913 * Get the security actions (in the form of flags) associated with the specified assembly.
9915 * @assembly: The assembly for which we want the declarative security flags.
9916 * Return the declarative security flags for the assembly.
9919 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9921 guint32 idx = 1; /* there is only one assembly */
9922 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9923 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9924 return mono_declsec_get_flags (assembly->image, idx);
9929 * Fill actions for the specific index (which may either be an encoded class token or
9930 * an encoded method token) from the metadata image.
9931 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9934 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9935 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9937 MonoBoolean result = FALSE;
9939 guint32 cols [MONO_DECL_SECURITY_SIZE];
9940 int index = mono_metadata_declsec_from_index (image, token);
9943 t = &image->tables [MONO_TABLE_DECLSECURITY];
9944 for (i = index; i < t->rows; i++) {
9945 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9947 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9950 /* if present only replace (class) permissions with method permissions */
9951 /* if empty accept either class or method permissions */
9952 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9953 if (!actions->demand.blob) {
9954 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9955 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9956 actions->demand.blob = (char*) (blob + 2);
9957 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9960 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9961 if (!actions->noncasdemand.blob) {
9962 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9963 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9964 actions->noncasdemand.blob = (char*) (blob + 2);
9965 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9968 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9969 if (!actions->demandchoice.blob) {
9970 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9971 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9972 actions->demandchoice.blob = (char*) (blob + 2);
9973 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9983 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9984 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9986 guint32 idx = mono_metadata_token_index (klass->type_token);
9987 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9988 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9989 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9993 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9994 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9996 guint32 idx = mono_method_get_index (method);
9997 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9998 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9999 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10003 * Collect all actions (that requires to generate code in mini) assigned for
10004 * the specified method.
10005 * Note: Don't use the content of actions if the function return FALSE.
10008 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10010 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
10011 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10012 MonoBoolean result = FALSE;
10015 /* quick exit if no declarative security is present in the metadata */
10016 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10019 /* we want the original as the wrapper is "free" of the security informations */
10020 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
10021 method = mono_marshal_method_from_wrapper (method);
10026 /* First we look for method-level attributes */
10027 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10028 mono_class_init (method->klass);
10029 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10031 result = mono_declsec_get_method_demands_params (method, demands,
10032 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10035 /* Here we use (or create) the class declarative cache to look for demands */
10036 flags = mono_declsec_flags_from_class (method->klass);
10037 if (flags & mask) {
10039 mono_class_init (method->klass);
10040 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10042 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10043 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10046 /* The boolean return value is used as a shortcut in case nothing needs to
10047 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10053 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10055 * Note: Don't use the content of actions if the function return FALSE.
10058 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10060 MonoBoolean result = FALSE;
10063 /* quick exit if no declarative security is present in the metadata */
10064 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10067 /* we want the original as the wrapper is "free" of the security informations */
10068 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
10069 method = mono_marshal_method_from_wrapper (method);
10074 /* results are independant - zeroize both */
10075 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10076 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10078 /* First we look for method-level attributes */
10079 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10080 mono_class_init (method->klass);
10082 result = mono_declsec_get_method_demands_params (method, cmethod,
10083 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10086 /* Here we use (or create) the class declarative cache to look for demands */
10087 flags = mono_declsec_flags_from_class (method->klass);
10088 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10089 mono_class_init (method->klass);
10091 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10092 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10099 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10101 * @klass The inherited class - this is the class that provides the security check (attributes)
10103 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10105 * Note: Don't use the content of actions if the function return FALSE.
10108 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10110 MonoBoolean result = FALSE;
10113 /* quick exit if no declarative security is present in the metadata */
10114 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10117 /* Here we use (or create) the class declarative cache to look for demands */
10118 flags = mono_declsec_flags_from_class (klass);
10119 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10120 mono_class_init (klass);
10121 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10123 result |= mono_declsec_get_class_demands_params (klass, demands,
10124 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10131 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10133 * Note: Don't use the content of actions if the function return FALSE.
10136 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10138 /* quick exit if no declarative security is present in the metadata */
10139 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10142 /* we want the original as the wrapper is "free" of the security informations */
10143 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
10144 method = mono_marshal_method_from_wrapper (method);
10149 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10150 mono_class_init (method->klass);
10151 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10153 return mono_declsec_get_method_demands_params (method, demands,
10154 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10161 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10163 guint32 cols [MONO_DECL_SECURITY_SIZE];
10167 int index = mono_metadata_declsec_from_index (image, token);
10171 t = &image->tables [MONO_TABLE_DECLSECURITY];
10172 for (i = index; i < t->rows; i++) {
10173 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10175 /* shortcut - index are ordered */
10176 if (token != cols [MONO_DECL_SECURITY_PARENT])
10179 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10180 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10181 entry->blob = (char*) (metadata + 2);
10182 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10191 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10193 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10194 guint32 idx = mono_method_get_index (method);
10195 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10196 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10197 return get_declsec_action (method->klass->image, idx, action, entry);
10203 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10206 guint32 flags = mono_declsec_flags_from_class (klass);
10207 if (declsec_flags_map [action] & flags) {
10208 guint32 idx = mono_metadata_token_index (klass->type_token);
10209 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10210 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10211 return get_declsec_action (klass->image, idx, action, entry);
10217 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10219 guint32 idx = 1; /* there is only one assembly */
10220 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10221 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10223 return get_declsec_action (assembly->image, idx, action, entry);
10227 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10229 MonoObject *res, *exc;
10231 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10232 static MonoMethod *method = NULL;
10234 if (!System_Reflection_Emit_TypeBuilder) {
10235 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10236 g_assert (System_Reflection_Emit_TypeBuilder);
10238 if (method == NULL) {
10239 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10244 * The result of mono_type_get_object () might be a System.MonoType but we
10245 * need a TypeBuilder so use klass->reflection_info.
10247 g_assert (klass->reflection_info);
10248 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10250 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10252 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10256 return *(MonoBoolean*)mono_object_unbox (res);