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/utils/mono-membar.h"
13 #include "mono/metadata/reflection.h"
14 #include "mono/metadata/tabledefs.h"
15 #include "mono/metadata/metadata-internals.h"
16 #include <mono/metadata/profiler-private.h>
17 #include "mono/metadata/class-internals.h"
18 #include "mono/metadata/gc-internal.h"
19 #include "mono/metadata/tokentype.h"
20 #include "mono/metadata/domain-internals.h"
21 #include "mono/metadata/opcodes.h"
22 #include "mono/metadata/assembly.h"
23 #include "mono/metadata/object-internals.h"
24 #include <mono/metadata/exception.h>
25 #include <mono/metadata/marshal.h>
26 #include <mono/metadata/security-manager.h>
35 #include "rawbuffer.h"
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
45 #define TEXT_OFFSET 512
46 #define CLI_H_SIZE 136
47 #define FILE_ALIGN 512
48 #define VIRT_ALIGN 8192
49 #define START_TEXT_RVA 0x00002000
52 MonoReflectionILGen *ilgen;
53 MonoReflectionType *rtype;
54 MonoArray *parameters;
55 MonoArray *generic_params;
56 MonoGenericContainer *generic_container;
62 guint32 *table_idx; /* note: it's a pointer */
66 MonoBoolean init_locals;
67 MonoBoolean skip_visibility;
68 MonoArray *return_modreq;
69 MonoArray *return_modopt;
70 MonoArray *param_modreq;
71 MonoArray *param_modopt;
72 MonoArray *permissions;
77 int charset, extra_flags, native_cc;
78 MonoString *dll, *dllentry;
79 } ReflectionMethodBuilder;
83 MonoReflectionGenericParam *gparam;
84 } GenericParamTableEntry;
86 const unsigned char table_sizes [MONO_TABLE_NUM] = {
96 MONO_INTERFACEIMPL_SIZE,
97 MONO_MEMBERREF_SIZE, /* 0x0A */
99 MONO_CUSTOM_ATTR_SIZE,
100 MONO_FIELD_MARSHAL_SIZE,
101 MONO_DECL_SECURITY_SIZE,
102 MONO_CLASS_LAYOUT_SIZE,
103 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
104 MONO_STAND_ALONE_SIGNATURE_SIZE,
108 MONO_PROPERTY_MAP_SIZE,
111 MONO_METHOD_SEMA_SIZE,
112 MONO_METHODIMPL_SIZE,
113 MONO_MODULEREF_SIZE, /* 0x1A */
119 MONO_ASSEMBLY_SIZE, /* 0x20 */
120 MONO_ASSEMBLY_PROCESSOR_SIZE,
121 MONO_ASSEMBLYOS_SIZE,
122 MONO_ASSEMBLYREF_SIZE,
123 MONO_ASSEMBLYREFPROC_SIZE,
124 MONO_ASSEMBLYREFOS_SIZE,
128 MONO_NESTED_CLASS_SIZE,
130 MONO_GENERICPARAM_SIZE, /* 0x2A */
131 MONO_METHODSPEC_SIZE,
132 MONO_GENPARCONSTRAINT_SIZE
136 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
137 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
138 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
139 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
140 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
141 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
142 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
143 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
144 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
145 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
146 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
147 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
148 static void ensure_runtime_vtable (MonoClass *klass);
149 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
150 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
151 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
152 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
153 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
154 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
157 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
158 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
159 static CRITICAL_SECTION reflection_mutex;
162 mono_reflection_init (void)
164 InitializeCriticalSection (&reflection_mutex);
168 sigbuffer_init (SigBuffer *buf, int size)
170 buf->buf = g_malloc (size);
172 buf->end = buf->buf + size;
176 sigbuffer_make_room (SigBuffer *buf, int size)
178 if (buf->end - buf->p < size) {
179 int new_size = buf->end - buf->buf + size + 32;
180 char *p = g_realloc (buf->buf, new_size);
181 size = buf->p - buf->buf;
184 buf->end = buf->buf + new_size;
189 sigbuffer_add_value (SigBuffer *buf, guint32 val)
191 sigbuffer_make_room (buf, 6);
192 mono_metadata_encode_value (val, buf->p, &buf->p);
196 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
198 sigbuffer_make_room (buf, 1);
204 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
206 sigbuffer_make_room (buf, size);
207 memcpy (buf->p, p, size);
212 sigbuffer_free (SigBuffer *buf)
220 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
224 mp_g_malloc (MonoMemPool *mp, guint size)
227 return mono_mempool_alloc (mp, size);
229 return g_malloc (size);
235 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
239 mp_g_malloc0 (MonoMemPool *mp, guint size)
242 return mono_mempool_alloc0 (mp, size);
244 return g_malloc0 (size);
250 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
251 * memory from the C heap.
254 mp_string_to_utf8 (MonoMemPool *mp, MonoString *s)
257 return mono_string_to_utf8_mp (mp, s);
259 return mono_string_to_utf8 (s);
262 #define mp_g_new(mp,struct_type, n_structs) \
263 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
265 #define mp_g_new0(mp,struct_type, n_structs) \
266 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
269 alloc_table (MonoDynamicTable *table, guint nrows)
272 g_assert (table->columns);
273 if (nrows + 1 >= table->alloc_rows) {
274 while (nrows + 1 >= table->alloc_rows) {
275 if (table->alloc_rows == 0)
276 table->alloc_rows = 16;
278 table->alloc_rows *= 2;
281 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
286 make_room_in_stream (MonoDynamicStream *stream, int size)
288 if (size <= stream->alloc_size)
291 while (stream->alloc_size <= size) {
292 if (stream->alloc_size < 4096)
293 stream->alloc_size = 4096;
295 stream->alloc_size *= 2;
298 stream->data = g_realloc (stream->data, stream->alloc_size);
302 string_heap_insert (MonoDynamicStream *sh, const char *str)
306 gpointer oldkey, oldval;
308 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
309 return GPOINTER_TO_UINT (oldval);
311 len = strlen (str) + 1;
314 make_room_in_stream (sh, idx + len);
317 * We strdup the string even if we already copy them in sh->data
318 * so that the string pointers in the hash remain valid even if
319 * we need to realloc sh->data. We may want to avoid that later.
321 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
322 memcpy (sh->data + idx, str, len);
328 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
330 char *name = mono_string_to_utf8 (str);
332 idx = string_heap_insert (sh, name);
338 string_heap_init (MonoDynamicStream *sh)
341 sh->alloc_size = 4096;
342 sh->data = g_malloc (4096);
343 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
344 string_heap_insert (sh, "");
348 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
352 make_room_in_stream (stream, stream->index + len);
353 memcpy (stream->data + stream->index, data, len);
355 stream->index += len;
357 * align index? Not without adding an additional param that controls it since
358 * we may store a blob value in pieces.
364 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
368 make_room_in_stream (stream, stream->index + len);
369 memset (stream->data + stream->index, 0, len);
371 stream->index += len;
376 stream_data_align (MonoDynamicStream *stream)
379 guint32 count = stream->index % 4;
381 /* we assume the stream data will be aligned */
383 mono_image_add_stream_data (stream, buf, 4 - count);
387 mono_blob_entry_hash (const char* str)
391 len = mono_metadata_decode_blob_size (str, &str);
395 for (str += 1; str < end; str++)
396 h = (h << 5) - h + *str;
404 mono_blob_entry_equal (const char *str1, const char *str2) {
408 len = mono_metadata_decode_blob_size (str1, &end1);
409 len2 = mono_metadata_decode_blob_size (str2, &end2);
412 return memcmp (end1, end2, len) == 0;
416 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
420 gpointer oldkey, oldval;
422 copy = g_malloc (s1+s2);
423 memcpy (copy, b1, s1);
424 memcpy (copy + s1, b2, s2);
425 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
427 idx = GPOINTER_TO_UINT (oldval);
429 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
430 mono_image_add_stream_data (&assembly->blob, b2, s2);
431 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
437 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
441 guint32 size = buf->p - buf->buf;
443 g_assert (size <= (buf->end - buf->buf));
444 mono_metadata_encode_value (size, b, &b);
445 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
449 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
450 * dest may be misaligned.
453 swap_with_size (char *dest, const char* val, int len, int nelem) {
454 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
457 for (elem = 0; elem < nelem; ++elem) {
483 g_assert_not_reached ();
489 memcpy (dest, val, len * nelem);
494 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
498 guint32 idx = 0, len;
500 len = str->length * 2;
501 mono_metadata_encode_value (len, b, &b);
502 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
504 char *swapped = g_malloc (2 * mono_string_length (str));
505 const char *p = (const char*)mono_string_chars (str);
507 swap_with_size (swapped, p, 2, mono_string_length (str));
508 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
512 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
517 /* modified version needed to handle building corlib */
519 my_mono_class_from_mono_type (MonoType *type) {
520 switch (type->type) {
521 case MONO_TYPE_ARRAY:
523 case MONO_TYPE_SZARRAY:
524 case MONO_TYPE_GENERICINST:
525 return mono_class_from_mono_type (type);
528 g_assert (type->data.generic_param->pklass);
529 return type->data.generic_param->pklass;
531 /* should be always valid when we reach this case... */
532 return type->data.klass;
537 default_class_from_mono_type (MonoType *type)
539 switch (type->type) {
540 case MONO_TYPE_OBJECT:
541 return mono_defaults.object_class;
543 return mono_defaults.void_class;
544 case MONO_TYPE_BOOLEAN:
545 return mono_defaults.boolean_class;
547 return mono_defaults.char_class;
549 return mono_defaults.sbyte_class;
551 return mono_defaults.byte_class;
553 return mono_defaults.int16_class;
555 return mono_defaults.uint16_class;
557 return mono_defaults.int32_class;
559 return mono_defaults.uint32_class;
561 return mono_defaults.int_class;
563 return mono_defaults.uint_class;
565 return mono_defaults.int64_class;
567 return mono_defaults.uint64_class;
569 return mono_defaults.single_class;
571 return mono_defaults.double_class;
572 case MONO_TYPE_STRING:
573 return mono_defaults.string_class;
575 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
576 g_assert_not_reached ();
583 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
586 MonoGenericInst *class_inst;
591 class_inst = gclass->context.class_inst;
593 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
594 klass = gclass->container_class;
595 sigbuffer_add_value (buf, klass->byval_arg.type);
596 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
598 sigbuffer_add_value (buf, class_inst->type_argc);
599 for (i = 0; i < class_inst->type_argc; ++i)
600 encode_type (assembly, class_inst->type_argv [i], buf);
605 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
608 g_assert_not_reached ();
613 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
617 case MONO_TYPE_BOOLEAN:
631 case MONO_TYPE_STRING:
632 case MONO_TYPE_OBJECT:
633 case MONO_TYPE_TYPEDBYREF:
634 sigbuffer_add_value (buf, type->type);
637 sigbuffer_add_value (buf, type->type);
638 encode_type (assembly, type->data.type, buf);
640 case MONO_TYPE_SZARRAY:
641 sigbuffer_add_value (buf, type->type);
642 encode_type (assembly, &type->data.klass->byval_arg, buf);
644 case MONO_TYPE_VALUETYPE:
645 case MONO_TYPE_CLASS: {
646 MonoClass *k = mono_class_from_mono_type (type);
648 if (k->generic_container) {
649 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
650 encode_generic_class (assembly, gclass, buf);
653 * Make sure we use the correct type.
655 sigbuffer_add_value (buf, k->byval_arg.type);
657 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
658 * otherwise two typerefs could point to the same type, leading to
659 * verification errors.
661 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
665 case MONO_TYPE_ARRAY:
666 sigbuffer_add_value (buf, type->type);
667 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
668 sigbuffer_add_value (buf, type->data.array->rank);
669 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
670 sigbuffer_add_value (buf, 0);
672 case MONO_TYPE_GENERICINST:
673 encode_generic_class (assembly, type->data.generic_class, buf);
677 sigbuffer_add_value (buf, type->type);
678 sigbuffer_add_value (buf, type->data.generic_param->num);
681 g_error ("need to encode type %x", type->type);
686 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
689 sigbuffer_add_value (buf, MONO_TYPE_VOID);
694 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
695 encode_type (assembly, type->type, buf);
699 g_assert_not_reached ();
704 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
709 for (i = 0; i < mono_array_length (modreq); ++i) {
710 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
711 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
712 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
716 for (i = 0; i < mono_array_length (modopt); ++i) {
717 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
718 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
719 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
725 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
729 guint32 nparams = sig->param_count;
735 sigbuffer_init (&buf, 32);
737 * FIXME: vararg, explicit_this, differenc call_conv values...
739 idx = sig->call_convention;
741 idx |= 0x20; /* hasthis */
742 if (sig->generic_param_count)
743 idx |= 0x10; /* generic */
744 sigbuffer_add_byte (&buf, idx);
745 if (sig->generic_param_count)
746 sigbuffer_add_value (&buf, sig->generic_param_count);
747 sigbuffer_add_value (&buf, nparams);
748 encode_type (assembly, sig->ret, &buf);
749 for (i = 0; i < nparams; ++i) {
750 if (i == sig->sentinelpos)
751 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
752 encode_type (assembly, sig->params [i], &buf);
754 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
755 sigbuffer_free (&buf);
760 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
763 * FIXME: reuse code from method_encode_signature().
767 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
768 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
769 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
772 sigbuffer_init (&buf, 32);
773 /* LAMESPEC: all the call conv spec is foobared */
774 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
775 if (mb->call_conv & 2)
776 idx |= 0x5; /* vararg */
777 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
778 idx |= 0x20; /* hasthis */
780 idx |= 0x10; /* generic */
781 sigbuffer_add_byte (&buf, idx);
783 sigbuffer_add_value (&buf, ngparams);
784 sigbuffer_add_value (&buf, nparams + notypes);
785 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
786 encode_reflection_type (assembly, mb->rtype, &buf);
787 for (i = 0; i < nparams; ++i) {
788 MonoArray *modreq = NULL;
789 MonoArray *modopt = NULL;
790 MonoReflectionType *pt;
792 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
793 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
794 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
795 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
796 encode_custom_modifiers (assembly, modreq, modopt, &buf);
797 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
798 encode_reflection_type (assembly, pt, &buf);
801 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
802 for (i = 0; i < notypes; ++i) {
803 MonoReflectionType *pt;
805 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
806 encode_reflection_type (assembly, pt, &buf);
809 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
810 sigbuffer_free (&buf);
815 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
817 MonoDynamicTable *table;
819 guint32 idx, sig_idx;
820 guint nl = mono_array_length (ilgen->locals);
824 sigbuffer_init (&buf, 32);
825 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
826 idx = table->next_idx ++;
828 alloc_table (table, table->rows);
829 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
831 sigbuffer_add_value (&buf, 0x07);
832 sigbuffer_add_value (&buf, nl);
833 for (i = 0; i < nl; ++i) {
834 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
837 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
839 encode_reflection_type (assembly, lb->type, &buf);
841 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
842 sigbuffer_free (&buf);
844 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
850 method_count_clauses (MonoReflectionILGen *ilgen)
852 guint32 num_clauses = 0;
855 MonoILExceptionInfo *ex_info;
856 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
857 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
858 if (ex_info->handlers)
859 num_clauses += mono_array_length (ex_info->handlers);
867 static MonoExceptionClause*
868 method_encode_clauses (MonoMemPool *mp, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
870 MonoExceptionClause *clauses;
871 MonoExceptionClause *clause;
872 MonoILExceptionInfo *ex_info;
873 MonoILExceptionBlock *ex_block;
874 guint32 finally_start;
875 int i, j, clause_index;;
877 clauses = mp_g_new0 (mp, MonoExceptionClause, num_clauses);
880 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
881 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
882 finally_start = ex_info->start + ex_info->len;
883 if (!ex_info->handlers)
885 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
886 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
887 clause = &(clauses [clause_index]);
889 clause->flags = ex_block->type;
890 clause->try_offset = ex_info->start;
892 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
893 clause->try_len = finally_start - ex_info->start;
895 clause->try_len = ex_info->len;
896 clause->handler_offset = ex_block->start;
897 clause->handler_len = ex_block->len;
898 if (ex_block->extype) {
899 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
901 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
902 clause->data.filter_offset = ex_block->filter_offset;
904 clause->data.filter_offset = 0;
906 finally_start = ex_block->start + ex_block->len;
916 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
922 gint32 num_locals = 0;
923 gint32 num_exception = 0;
926 char fat_header [12];
929 guint32 local_sig = 0;
930 guint32 header_size = 12;
933 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
934 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
938 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
940 code = mb->ilgen->code;
941 code_size = mb->ilgen->code_len;
942 max_stack = mb->ilgen->max_stack;
943 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
944 if (mb->ilgen->ex_handlers)
945 num_exception = method_count_clauses (mb->ilgen);
949 char *name = mono_string_to_utf8 (mb->name);
950 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
951 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
954 mono_raise_exception (exception);
957 code_size = mono_array_length (code);
958 max_stack = 8; /* we probably need to run a verifier on the code... */
961 stream_data_align (&assembly->code);
963 /* check for exceptions, maxstack, locals */
964 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
966 if (code_size < 64 && !(code_size & 1)) {
967 flags = (code_size << 2) | 0x2;
968 } else if (code_size < 32 && (code_size & 1)) {
969 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
973 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
974 /* add to the fixup todo list */
975 if (mb->ilgen && mb->ilgen->num_token_fixups)
976 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
977 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
978 return assembly->text_rva + idx;
982 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
984 * FIXME: need to set also the header size in fat_flags.
985 * (and more sects and init locals flags)
989 fat_flags |= METHOD_HEADER_MORE_SECTS;
991 fat_flags |= METHOD_HEADER_INIT_LOCALS;
992 fat_header [0] = fat_flags;
993 fat_header [1] = (header_size / 4 ) << 4;
994 short_value = GUINT16_TO_LE (max_stack);
995 memcpy (fat_header + 2, &short_value, 2);
996 int_value = GUINT32_TO_LE (code_size);
997 memcpy (fat_header + 4, &int_value, 4);
998 int_value = GUINT32_TO_LE (local_sig);
999 memcpy (fat_header + 8, &int_value, 4);
1000 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1001 /* add to the fixup todo list */
1002 if (mb->ilgen && mb->ilgen->num_token_fixups)
1003 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1005 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1006 if (num_exception) {
1007 unsigned char sheader [4];
1008 MonoILExceptionInfo * ex_info;
1009 MonoILExceptionBlock * ex_block;
1012 stream_data_align (&assembly->code);
1013 /* always use fat format for now */
1014 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1015 num_exception *= 6 * sizeof (guint32);
1016 num_exception += 4; /* include the size of the header */
1017 sheader [1] = num_exception & 0xff;
1018 sheader [2] = (num_exception >> 8) & 0xff;
1019 sheader [3] = (num_exception >> 16) & 0xff;
1020 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1021 /* fat header, so we are already aligned */
1023 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1024 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1025 if (ex_info->handlers) {
1026 int finally_start = ex_info->start + ex_info->len;
1027 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1029 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1031 val = GUINT32_TO_LE (ex_block->type);
1032 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1034 val = GUINT32_TO_LE (ex_info->start);
1035 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1036 /* need fault, too, probably */
1037 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1038 val = GUINT32_TO_LE (finally_start - ex_info->start);
1040 val = GUINT32_TO_LE (ex_info->len);
1041 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1042 /* handler offset */
1043 val = GUINT32_TO_LE (ex_block->start);
1044 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1046 val = GUINT32_TO_LE (ex_block->len);
1047 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1048 finally_start = ex_block->start + ex_block->len;
1049 if (ex_block->extype) {
1050 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1052 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1053 val = ex_block->filter_offset;
1057 val = GUINT32_TO_LE (val);
1058 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1059 /*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",
1060 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);*/
1063 g_error ("No clauses for ex info block %d", i);
1067 return assembly->text_rva + idx;
1071 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1074 MonoDynamicTable *table;
1077 table = &assembly->tables [table_idx];
1079 g_assert (col < table->columns);
1081 values = table->values + table->columns;
1082 for (i = 1; i <= table->rows; ++i) {
1083 if (values [col] == token)
1085 values += table->columns;
1091 * LOCKING: Acquires the loader lock.
1093 static MonoCustomAttrInfo*
1094 lookup_custom_attr (MonoImage *image, gpointer member)
1096 MonoCustomAttrInfo* res;
1098 mono_loader_lock ();
1099 res = mono_property_hash_lookup (image->property_hash, member, MONO_PROP_DYNAMIC_CATTR);
1100 mono_loader_unlock ();
1105 return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1109 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1111 /* FIXME: Need to do more checks */
1112 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1113 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1115 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1122 static MonoCustomAttrInfo*
1123 mono_custom_attrs_from_builders (MonoMemPool *mp, MonoImage *image, MonoArray *cattrs)
1125 int i, index, count, not_visible;
1126 MonoCustomAttrInfo *ainfo;
1127 MonoReflectionCustomAttr *cattr;
1131 /* FIXME: check in assembly the Run flag is set */
1133 count = mono_array_length (cattrs);
1135 /* Skip nonpublic attributes since MS.NET seems to do the same */
1136 /* FIXME: This needs to be done more globally */
1138 for (i = 0; i < count; ++i) {
1139 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1140 if (!custom_attr_visible (image, cattr))
1143 count -= not_visible;
1145 ainfo = mp_g_malloc0 (mp, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1147 ainfo->image = image;
1148 ainfo->num_attrs = count;
1149 ainfo->cached = mp != NULL;
1151 mono_loader_lock ();
1152 for (i = 0; i < count; ++i) {
1153 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1154 if (custom_attr_visible (image, cattr)) {
1155 unsigned char *saved = mono_mempool_alloc (image->mempool, mono_array_length (cattr->data));
1156 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1157 ainfo->attrs [index].ctor = cattr->ctor->method;
1158 ainfo->attrs [index].data = saved;
1159 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1163 mono_loader_unlock ();
1169 * LOCKING: Acquires the loader lock.
1172 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1174 MonoCustomAttrInfo *ainfo, *tmp;
1176 if (!cattrs || !mono_array_length (cattrs))
1179 ainfo = mono_custom_attrs_from_builders (image->mempool, image, cattrs);
1180 mono_loader_lock ();
1181 tmp = mono_property_hash_lookup (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR);
1183 mono_custom_attrs_free (tmp);
1184 mono_property_hash_insert (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1185 mono_loader_unlock ();
1189 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1196 * idx is the table index of the object
1197 * type is one of MONO_CUSTOM_ATTR_*
1200 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1202 MonoDynamicTable *table;
1203 MonoReflectionCustomAttr *cattr;
1205 guint32 count, i, token;
1207 char *p = blob_size;
1209 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1212 count = mono_array_length (cattrs);
1213 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1214 table->rows += count;
1215 alloc_table (table, table->rows);
1216 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1217 idx <<= MONO_CUSTOM_ATTR_BITS;
1219 for (i = 0; i < count; ++i) {
1220 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1221 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1222 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1223 type = mono_metadata_token_index (token);
1224 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1225 switch (mono_metadata_token_table (token)) {
1226 case MONO_TABLE_METHOD:
1227 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1229 case MONO_TABLE_MEMBERREF:
1230 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1233 g_warning ("got wrong token in custom attr");
1236 values [MONO_CUSTOM_ATTR_TYPE] = type;
1238 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1239 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1240 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1241 values += MONO_CUSTOM_ATTR_SIZE;
1247 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1249 MonoDynamicTable *table;
1251 guint32 count, i, idx;
1252 MonoReflectionPermissionSet *perm;
1257 count = mono_array_length (permissions);
1258 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1259 table->rows += count;
1260 alloc_table (table, table->rows);
1262 for (i = 0; i < mono_array_length (permissions); ++i) {
1263 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1265 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1267 idx = mono_metadata_token_index (parent_token);
1268 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1269 switch (mono_metadata_token_table (parent_token)) {
1270 case MONO_TABLE_TYPEDEF:
1271 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1273 case MONO_TABLE_METHOD:
1274 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1276 case MONO_TABLE_ASSEMBLY:
1277 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1280 g_assert_not_reached ();
1283 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1284 values [MONO_DECL_SECURITY_PARENT] = idx;
1285 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1292 * Fill in the MethodDef and ParamDef tables for a method.
1293 * This is used for both normal methods and constructors.
1296 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1298 MonoDynamicTable *table;
1302 /* room in this table is already allocated */
1303 table = &assembly->tables [MONO_TABLE_METHOD];
1304 *mb->table_idx = table->next_idx ++;
1305 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1306 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1307 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1308 values [MONO_METHOD_FLAGS] = mb->attrs;
1309 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1310 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1311 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1313 table = &assembly->tables [MONO_TABLE_PARAM];
1314 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1316 mono_image_add_decl_security (assembly,
1317 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1320 MonoDynamicTable *mtable;
1323 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1324 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1327 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1328 if (mono_array_get (mb->pinfo, gpointer, i))
1331 table->rows += count;
1332 alloc_table (table, table->rows);
1333 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1334 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1335 MonoReflectionParamBuilder *pb;
1336 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1337 values [MONO_PARAM_FLAGS] = pb->attrs;
1338 values [MONO_PARAM_SEQUENCE] = i;
1339 if (pb->name != NULL) {
1340 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1342 values [MONO_PARAM_NAME] = 0;
1344 values += MONO_PARAM_SIZE;
1345 if (pb->marshal_info) {
1347 alloc_table (mtable, mtable->rows);
1348 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1349 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1350 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1352 pb->table_idx = table->next_idx++;
1353 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1354 guint32 field_type = 0;
1355 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1357 alloc_table (mtable, mtable->rows);
1358 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1359 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1360 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1361 mvalues [MONO_CONSTANT_TYPE] = field_type;
1362 mvalues [MONO_CONSTANT_PADDING] = 0;
1370 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1372 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1374 rmb->ilgen = mb->ilgen;
1375 rmb->rtype = mb->rtype;
1376 rmb->parameters = mb->parameters;
1377 rmb->generic_params = mb->generic_params;
1378 rmb->generic_container = mb->generic_container;
1379 rmb->opt_types = NULL;
1380 rmb->pinfo = mb->pinfo;
1381 rmb->attrs = mb->attrs;
1382 rmb->iattrs = mb->iattrs;
1383 rmb->call_conv = mb->call_conv;
1384 rmb->code = mb->code;
1385 rmb->type = mb->type;
1386 rmb->name = mb->name;
1387 rmb->table_idx = &mb->table_idx;
1388 rmb->init_locals = mb->init_locals;
1389 rmb->skip_visibility = FALSE;
1390 rmb->return_modreq = mb->return_modreq;
1391 rmb->return_modopt = mb->return_modopt;
1392 rmb->param_modreq = mb->param_modreq;
1393 rmb->param_modopt = mb->param_modopt;
1394 rmb->permissions = mb->permissions;
1395 rmb->mhandle = mb->mhandle;
1400 rmb->charset = mb->charset;
1401 rmb->extra_flags = mb->extra_flags;
1402 rmb->native_cc = mb->native_cc;
1403 rmb->dllentry = mb->dllentry;
1409 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1411 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1413 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1415 rmb->ilgen = mb->ilgen;
1416 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1417 rmb->parameters = mb->parameters;
1418 rmb->generic_params = NULL;
1419 rmb->generic_container = NULL;
1420 rmb->opt_types = NULL;
1421 rmb->pinfo = mb->pinfo;
1422 rmb->attrs = mb->attrs;
1423 rmb->iattrs = mb->iattrs;
1424 rmb->call_conv = mb->call_conv;
1426 rmb->type = mb->type;
1427 rmb->name = mono_string_new (mono_domain_get (), name);
1428 rmb->table_idx = &mb->table_idx;
1429 rmb->init_locals = mb->init_locals;
1430 rmb->skip_visibility = FALSE;
1431 rmb->return_modreq = NULL;
1432 rmb->return_modopt = NULL;
1433 rmb->param_modreq = mb->param_modreq;
1434 rmb->param_modopt = mb->param_modopt;
1435 rmb->permissions = mb->permissions;
1436 rmb->mhandle = mb->mhandle;
1442 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1444 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1446 rmb->ilgen = mb->ilgen;
1447 rmb->rtype = mb->rtype;
1448 rmb->parameters = mb->parameters;
1449 rmb->generic_params = NULL;
1450 rmb->generic_container = NULL;
1451 rmb->opt_types = NULL;
1453 rmb->attrs = mb->attrs;
1455 rmb->call_conv = mb->call_conv;
1457 rmb->type = (MonoObject *) mb->owner;
1458 rmb->name = mb->name;
1459 rmb->table_idx = NULL;
1460 rmb->init_locals = mb->init_locals;
1461 rmb->skip_visibility = mb->skip_visibility;
1462 rmb->return_modreq = NULL;
1463 rmb->return_modopt = NULL;
1464 rmb->param_modreq = NULL;
1465 rmb->param_modopt = NULL;
1466 rmb->permissions = NULL;
1467 rmb->mhandle = mb->mhandle;
1473 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1475 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1476 MonoDynamicTable *table;
1480 if (!mb->override_method)
1483 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1485 alloc_table (table, table->rows);
1486 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1487 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1488 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1490 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1491 switch (mono_metadata_token_table (tok)) {
1492 case MONO_TABLE_MEMBERREF:
1493 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1495 case MONO_TABLE_METHOD:
1496 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1499 g_assert_not_reached ();
1501 values [MONO_METHODIMPL_DECLARATION] = tok;
1505 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1507 MonoDynamicTable *table;
1509 ReflectionMethodBuilder rmb;
1512 reflection_methodbuilder_from_method_builder (&rmb, mb);
1514 mono_image_basic_method (&rmb, assembly);
1515 mb->table_idx = *rmb.table_idx;
1517 if (mb->dll) { /* It's a P/Invoke method */
1519 /* map CharSet values to on-disk values */
1520 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1521 int extra_flags = mb->extra_flags;
1522 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1524 alloc_table (table, table->rows);
1525 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1527 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1528 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1530 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1532 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1533 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1534 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1535 table = &assembly->tables [MONO_TABLE_MODULEREF];
1537 alloc_table (table, table->rows);
1538 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1539 values [MONO_IMPLMAP_SCOPE] = table->rows;
1543 if (mb->generic_params) {
1544 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1545 table->rows += mono_array_length (mb->generic_params);
1546 alloc_table (table, table->rows);
1547 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1548 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1550 mono_image_get_generic_param_info (
1551 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1558 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1560 ReflectionMethodBuilder rmb;
1562 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1564 mono_image_basic_method (&rmb, assembly);
1565 mb->table_idx = *rmb.table_idx;
1569 type_get_fully_qualified_name (MonoType *type)
1571 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1575 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1579 klass = my_mono_class_from_mono_type (type);
1581 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1582 ta = klass->image->assembly;
1583 if (ta->dynamic || (ta == ass)) {
1584 if (klass->generic_class || klass->generic_container)
1585 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1586 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1588 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1591 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1595 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1600 if (!assembly->save)
1603 sigbuffer_init (&buf, 32);
1605 sigbuffer_add_value (&buf, 0x06);
1606 /* encode custom attributes before the type */
1607 encode_type (assembly, type, &buf);
1608 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1609 sigbuffer_free (&buf);
1614 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1619 sigbuffer_init (&buf, 32);
1621 sigbuffer_add_value (&buf, 0x06);
1622 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1623 /* encode custom attributes before the type */
1624 encode_reflection_type (assembly, fb->type, &buf);
1625 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1626 sigbuffer_free (&buf);
1631 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1632 char blob_size [64];
1633 char *b = blob_size;
1636 guint32 idx = 0, len = 0, dummy = 0;
1638 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1639 guint32 fpa_double [2];
1644 p = buf = g_malloc (64);
1646 *ret_type = MONO_TYPE_CLASS;
1648 box_val = (char*)&dummy;
1650 box_val = ((char*)val) + sizeof (MonoObject);
1651 *ret_type = val->vtable->klass->byval_arg.type;
1654 switch (*ret_type) {
1655 case MONO_TYPE_BOOLEAN:
1660 case MONO_TYPE_CHAR:
1677 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1678 fpa_p = (guint32*)box_val;
1679 fpa_double [0] = fpa_p [1];
1680 fpa_double [1] = fpa_p [0];
1681 box_val = (char*)fpa_double;
1685 case MONO_TYPE_VALUETYPE:
1686 if (val->vtable->klass->enumtype) {
1687 *ret_type = val->vtable->klass->enum_basetype->type;
1690 g_error ("we can't encode valuetypes");
1691 case MONO_TYPE_CLASS:
1693 case MONO_TYPE_STRING: {
1694 MonoString *str = (MonoString*)val;
1695 /* there is no signature */
1696 len = str->length * 2;
1697 mono_metadata_encode_value (len, b, &b);
1698 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1700 char *swapped = g_malloc (2 * mono_string_length (str));
1701 const char *p = (const char*)mono_string_chars (str);
1703 swap_with_size (swapped, p, 2, mono_string_length (str));
1704 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1708 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1714 case MONO_TYPE_GENERICINST:
1715 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1718 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1721 /* there is no signature */
1722 mono_metadata_encode_value (len, b, &b);
1723 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1724 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1725 swap_with_size (blob_size, box_val, len, 1);
1726 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1728 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1736 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1741 sigbuffer_init (&buf, 32);
1743 sigbuffer_add_value (&buf, minfo->type);
1745 switch (minfo->type) {
1746 case MONO_NATIVE_BYVALTSTR:
1747 case MONO_NATIVE_BYVALARRAY:
1748 sigbuffer_add_value (&buf, minfo->count);
1750 case MONO_NATIVE_LPARRAY:
1751 if (minfo->eltype || minfo->has_size) {
1752 sigbuffer_add_value (&buf, minfo->eltype);
1753 if (minfo->has_size) {
1754 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1755 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1757 /* LAMESPEC: ElemMult is undocumented */
1758 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1762 case MONO_NATIVE_CUSTOM:
1764 str = mono_string_to_utf8 (minfo->guid);
1766 sigbuffer_add_value (&buf, len);
1767 sigbuffer_add_mem (&buf, str, len);
1770 sigbuffer_add_value (&buf, 0);
1772 /* native type name */
1773 sigbuffer_add_value (&buf, 0);
1774 /* custom marshaler type name */
1775 if (minfo->marshaltype || minfo->marshaltyperef) {
1776 if (minfo->marshaltyperef)
1777 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1779 str = mono_string_to_utf8 (minfo->marshaltype);
1781 sigbuffer_add_value (&buf, len);
1782 sigbuffer_add_mem (&buf, str, len);
1785 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1786 sigbuffer_add_value (&buf, 0);
1788 if (minfo->mcookie) {
1789 str = mono_string_to_utf8 (minfo->mcookie);
1791 sigbuffer_add_value (&buf, len);
1792 sigbuffer_add_mem (&buf, str, len);
1795 sigbuffer_add_value (&buf, 0);
1801 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1802 sigbuffer_free (&buf);
1807 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1809 MonoDynamicTable *table;
1812 /* maybe this fixup should be done in the C# code */
1813 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1814 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1815 table = &assembly->tables [MONO_TABLE_FIELD];
1816 fb->table_idx = table->next_idx ++;
1817 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1818 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1819 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1820 values [MONO_FIELD_FLAGS] = fb->attrs;
1821 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1823 if (fb->offset != -1) {
1824 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1826 alloc_table (table, table->rows);
1827 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1828 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1829 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1831 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1832 guint32 field_type = 0;
1833 table = &assembly->tables [MONO_TABLE_CONSTANT];
1835 alloc_table (table, table->rows);
1836 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1837 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1838 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1839 values [MONO_CONSTANT_TYPE] = field_type;
1840 values [MONO_CONSTANT_PADDING] = 0;
1842 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1844 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1846 alloc_table (table, table->rows);
1847 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1848 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1850 * We store it in the code section because it's simpler for now.
1853 if (mono_array_length (fb->rva_data) >= 10)
1854 stream_data_align (&assembly->code);
1855 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1857 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1858 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1860 if (fb->marshal_info) {
1861 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1863 alloc_table (table, table->rows);
1864 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1865 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1866 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1871 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1874 guint32 nparams = 0;
1875 MonoReflectionMethodBuilder *mb = fb->get_method;
1876 MonoReflectionMethodBuilder *smb = fb->set_method;
1879 if (mb && mb->parameters)
1880 nparams = mono_array_length (mb->parameters);
1881 if (!mb && smb && smb->parameters)
1882 nparams = mono_array_length (smb->parameters) - 1;
1883 sigbuffer_init (&buf, 32);
1884 sigbuffer_add_byte (&buf, 0x08);
1885 sigbuffer_add_value (&buf, nparams);
1887 encode_reflection_type (assembly, mb->rtype, &buf);
1888 for (i = 0; i < nparams; ++i) {
1889 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1890 encode_reflection_type (assembly, pt, &buf);
1892 } else if (smb && smb->parameters) {
1893 /* the property type is the last param */
1894 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1895 for (i = 0; i < nparams; ++i) {
1896 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1897 encode_reflection_type (assembly, pt, &buf);
1900 encode_reflection_type (assembly, fb->type, &buf);
1903 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1904 sigbuffer_free (&buf);
1909 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1911 MonoDynamicTable *table;
1913 guint num_methods = 0;
1917 * we need to set things in the following tables:
1918 * PROPERTYMAP (info already filled in _get_type_info ())
1919 * PROPERTY (rows already preallocated in _get_type_info ())
1920 * METHOD (method info already done with the generic method code)
1923 table = &assembly->tables [MONO_TABLE_PROPERTY];
1924 pb->table_idx = table->next_idx ++;
1925 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1926 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1927 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1928 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1930 /* FIXME: we still don't handle 'other' methods */
1931 if (pb->get_method) num_methods ++;
1932 if (pb->set_method) num_methods ++;
1934 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1935 table->rows += num_methods;
1936 alloc_table (table, table->rows);
1938 if (pb->get_method) {
1939 semaidx = table->next_idx ++;
1940 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1941 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1942 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1943 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1945 if (pb->set_method) {
1946 semaidx = table->next_idx ++;
1947 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1948 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1949 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1950 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1955 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1957 MonoDynamicTable *table;
1959 guint num_methods = 0;
1963 * we need to set things in the following tables:
1964 * EVENTMAP (info already filled in _get_type_info ())
1965 * EVENT (rows already preallocated in _get_type_info ())
1966 * METHOD (method info already done with the generic method code)
1969 table = &assembly->tables [MONO_TABLE_EVENT];
1970 eb->table_idx = table->next_idx ++;
1971 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1972 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1973 values [MONO_EVENT_FLAGS] = eb->attrs;
1974 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1977 * FIXME: we still don't handle 'other' methods
1979 if (eb->add_method) num_methods ++;
1980 if (eb->remove_method) num_methods ++;
1981 if (eb->raise_method) num_methods ++;
1983 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1984 table->rows += num_methods;
1985 alloc_table (table, table->rows);
1987 if (eb->add_method) {
1988 semaidx = table->next_idx ++;
1989 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1990 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1991 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1992 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1994 if (eb->remove_method) {
1995 semaidx = table->next_idx ++;
1996 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1997 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1998 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1999 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2001 if (eb->raise_method) {
2002 semaidx = table->next_idx ++;
2003 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2004 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2005 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2006 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2011 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2013 MonoDynamicTable *table;
2014 guint32 num_constraints, i;
2018 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2019 num_constraints = gparam->iface_constraints ?
2020 mono_array_length (gparam->iface_constraints) : 0;
2021 table->rows += num_constraints;
2022 if (gparam->base_type)
2024 alloc_table (table, table->rows);
2026 if (gparam->base_type) {
2027 table_idx = table->next_idx ++;
2028 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2030 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2031 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2032 assembly, gparam->base_type->type);
2035 for (i = 0; i < num_constraints; i++) {
2036 MonoReflectionType *constraint = mono_array_get (
2037 gparam->iface_constraints, gpointer, i);
2039 table_idx = table->next_idx ++;
2040 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2042 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2043 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2044 assembly, constraint->type);
2049 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2051 GenericParamTableEntry *entry;
2054 * The GenericParam table must be sorted according to the `owner' field.
2055 * We need to do this sorting prior to writing the GenericParamConstraint
2056 * table, since we have to use the final GenericParam table indices there
2057 * and they must also be sorted.
2060 entry = g_new0 (GenericParamTableEntry, 1);
2061 entry->owner = owner;
2063 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2064 MONO_GC_REGISTER_ROOT (entry->gparam);
2066 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2068 g_ptr_array_add (assembly->gen_params, entry);
2072 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2074 MonoDynamicTable *table;
2075 MonoGenericParam *param;
2079 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2080 table_idx = table->next_idx ++;
2081 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2083 param = entry->gparam->type.type->data.generic_param;
2085 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2086 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2087 values [MONO_GENERICPARAM_NUMBER] = param->num;
2088 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2090 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2092 encode_constraints (entry->gparam, table_idx, assembly);
2096 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2098 MonoDynamicTable *table;
2101 guint32 cols [MONO_ASSEMBLY_SIZE];
2105 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2108 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2109 table = &assembly->tables [MONO_TABLE_MODULEREF];
2110 token = table->next_idx ++;
2112 alloc_table (table, table->rows);
2113 values = table->values + token * MONO_MODULEREF_SIZE;
2114 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2116 token <<= MONO_RESOLTION_SCOPE_BITS;
2117 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2118 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2123 if (image->assembly->dynamic)
2125 memset (cols, 0, sizeof (cols));
2127 /* image->assembly->image is the manifest module */
2128 image = image->assembly->image;
2129 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2132 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2133 token = table->next_idx ++;
2135 alloc_table (table, table->rows);
2136 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2137 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2138 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2139 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2140 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2141 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2142 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2143 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2144 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2146 if (strcmp ("", image->assembly->aname.culture)) {
2147 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2148 image->assembly->aname.culture);
2151 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2152 guchar pubtoken [9];
2154 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2155 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2157 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2159 token <<= MONO_RESOLTION_SCOPE_BITS;
2160 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2161 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2166 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2168 MonoDynamicTable *table;
2173 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2176 sigbuffer_init (&buf, 32);
2177 switch (type->type) {
2178 case MONO_TYPE_FNPTR:
2180 case MONO_TYPE_SZARRAY:
2181 case MONO_TYPE_ARRAY:
2183 case MONO_TYPE_MVAR:
2184 case MONO_TYPE_GENERICINST:
2185 encode_type (assembly, type, &buf);
2187 case MONO_TYPE_CLASS:
2188 case MONO_TYPE_VALUETYPE: {
2189 MonoClass *k = mono_class_from_mono_type (type);
2190 if (!k || !k->generic_container) {
2191 sigbuffer_free (&buf);
2194 encode_type (assembly, type, &buf);
2198 sigbuffer_free (&buf);
2202 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2203 if (assembly->save) {
2204 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2205 alloc_table (table, table->rows + 1);
2206 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2207 values [MONO_TYPESPEC_SIGNATURE] = token;
2209 sigbuffer_free (&buf);
2211 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2212 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2218 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2220 MonoDynamicTable *table;
2222 guint32 token, scope, enclosing;
2225 /* if the type requires a typespec, we must try that first*/
2226 if (try_typespec && (token = create_typespec (assembly, type)))
2228 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2231 klass = my_mono_class_from_mono_type (type);
2233 klass = mono_class_from_mono_type (type);
2236 * If it's in the same module and not a generic type parameter:
2238 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2239 (type->type != MONO_TYPE_MVAR)) {
2240 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2241 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2242 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2246 if (klass->nested_in) {
2247 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2248 /* get the typeref idx of the enclosing type */
2249 enclosing >>= MONO_TYPEDEFORREF_BITS;
2250 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2252 scope = resolution_scope_from_image (assembly, klass->image);
2254 table = &assembly->tables [MONO_TABLE_TYPEREF];
2255 if (assembly->save) {
2256 alloc_table (table, table->rows + 1);
2257 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2258 values [MONO_TYPEREF_SCOPE] = scope;
2259 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2260 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2262 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2263 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2265 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2270 * Despite the name, we handle also TypeSpec (with the above helper).
2273 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2275 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2279 * Insert a memberef row into the metadata: the token that point to the memberref
2280 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2281 * mono_image_get_fieldref_token()).
2282 * The sig param is an index to an already built signature.
2285 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2287 MonoDynamicTable *table;
2289 guint32 token, pclass;
2292 parent = mono_image_typedef_or_ref (assembly, type);
2293 switch (parent & MONO_TYPEDEFORREF_MASK) {
2294 case MONO_TYPEDEFORREF_TYPEREF:
2295 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2297 case MONO_TYPEDEFORREF_TYPESPEC:
2298 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2300 case MONO_TYPEDEFORREF_TYPEDEF:
2301 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2304 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2307 /* extract the index */
2308 parent >>= MONO_TYPEDEFORREF_BITS;
2310 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2312 if (assembly->save) {
2313 alloc_table (table, table->rows + 1);
2314 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2315 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2316 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2317 values [MONO_MEMBERREF_SIGNATURE] = sig;
2320 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2327 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2330 MonoMethodSignature *sig;
2332 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2337 * A methodref signature can't contain an unmanaged calling convention.
2339 sig = mono_metadata_signature_dup (mono_method_signature (method));
2340 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2341 sig->call_convention = MONO_CALL_DEFAULT;
2342 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2343 method->name, method_encode_signature (assembly, sig));
2345 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2350 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2353 ReflectionMethodBuilder rmb;
2356 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2360 name = mono_string_to_utf8 (method->name);
2361 reflection_methodbuilder_from_method_builder (&rmb, method);
2364 * A methodref signature can't contain an unmanaged calling convention.
2365 * Since some flags are encoded as part of call_conv, we need to check against it.
2367 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2368 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2369 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2370 name, method_builder_encode_signature (assembly, &rmb));
2373 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2378 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2379 const gchar *name, guint32 sig)
2381 MonoDynamicTable *table;
2385 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2387 if (assembly->save) {
2388 alloc_table (table, table->rows + 1);
2389 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2390 values [MONO_MEMBERREF_CLASS] = original;
2391 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2392 values [MONO_MEMBERREF_SIGNATURE] = sig;
2395 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2402 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2406 guint32 nparams = mono_array_length (mb->generic_params);
2409 if (!assembly->save)
2412 sigbuffer_init (&buf, 32);
2414 sigbuffer_add_value (&buf, 0xa);
2415 sigbuffer_add_value (&buf, nparams);
2417 for (i = 0; i < nparams; i++) {
2418 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2419 sigbuffer_add_value (&buf, i);
2422 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2423 sigbuffer_free (&buf);
2428 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2430 MonoDynamicTable *table;
2432 guint32 token, mtoken = 0;
2434 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2438 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2440 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2441 switch (mono_metadata_token_table (mtoken)) {
2442 case MONO_TABLE_MEMBERREF:
2443 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2445 case MONO_TABLE_METHOD:
2446 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2449 g_assert_not_reached ();
2452 if (assembly->save) {
2453 alloc_table (table, table->rows + 1);
2454 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2455 values [MONO_METHODSPEC_METHOD] = mtoken;
2456 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2459 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2462 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2467 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2471 if (mb->generic_params && create_methodspec)
2472 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2474 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2478 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2479 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2484 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2487 ReflectionMethodBuilder rmb;
2490 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2494 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2496 name = mono_string_to_utf8 (rmb.name);
2497 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2498 name, method_builder_encode_signature (assembly, &rmb));
2501 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2506 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2511 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2514 g_assert (f->field->parent);
2515 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2516 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2517 f->field->name, fieldref_encode_signature (assembly, type));
2518 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2523 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2527 MonoGenericClass *gclass;
2528 MonoDynamicGenericClass *dgclass;
2529 MonoReflectionFieldBuilder *fb = f->fb;
2532 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2535 klass = mono_class_from_mono_type (f->inst->type.type);
2536 gclass = f->inst->type.type->data.generic_class;
2537 g_assert (gclass->is_dynamic);
2538 dgclass = (MonoDynamicGenericClass *) gclass;
2540 name = mono_string_to_utf8 (fb->name);
2541 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2542 fieldref_encode_signature (assembly, fb->type->type));
2544 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2549 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2553 MonoGenericClass *gclass;
2554 MonoDynamicGenericClass *dgclass;
2555 MonoReflectionCtorBuilder *cb = c->cb;
2556 ReflectionMethodBuilder rmb;
2559 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2561 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2564 klass = mono_class_from_mono_type (c->inst->type.type);
2565 gclass = c->inst->type.type->data.generic_class;
2566 g_assert (gclass->is_dynamic);
2567 dgclass = (MonoDynamicGenericClass *) gclass;
2569 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2571 name = mono_string_to_utf8 (rmb.name);
2573 sig = method_builder_encode_signature (assembly, &rmb);
2575 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2578 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2583 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2587 MonoGenericClass *gclass;
2588 MonoReflectionMethodBuilder *mb = m->mb;
2589 ReflectionMethodBuilder rmb;
2592 if (create_methodspec && mb->generic_params)
2594 g_assert_not_reached ();
2596 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2599 klass = mono_class_from_mono_type (m->inst->type.type);
2600 gclass = m->inst->type.type->data.generic_class;
2601 g_assert (gclass->is_dynamic);
2603 reflection_methodbuilder_from_method_builder (&rmb, mb);
2605 name = mono_string_to_utf8 (rmb.name);
2607 sig = method_builder_encode_signature (assembly, &rmb);
2609 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2612 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2617 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2621 guint32 nparams = context->method_inst->type_argc;
2624 if (!assembly->save)
2627 sigbuffer_init (&buf, 32);
2629 * FIXME: vararg, explicit_this, differenc call_conv values...
2631 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2632 sigbuffer_add_value (&buf, nparams);
2634 for (i = 0; i < nparams; i++)
2635 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2637 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2638 sigbuffer_free (&buf);
2643 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2645 MonoDynamicTable *table;
2647 guint32 token, mtoken = 0, sig;
2648 MonoMethodInflated *imethod;
2649 MonoMethod *declaring;
2651 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2653 g_assert (method->is_inflated);
2654 imethod = (MonoMethodInflated *) method;
2655 declaring = imethod->declaring;
2657 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2658 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2660 if (!mono_method_signature (declaring)->generic_param_count)
2663 switch (mono_metadata_token_table (mtoken)) {
2664 case MONO_TABLE_MEMBERREF:
2665 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2667 case MONO_TABLE_METHOD:
2668 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2671 g_assert_not_reached ();
2674 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2676 if (assembly->save) {
2677 alloc_table (table, table->rows + 1);
2678 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2679 values [MONO_METHODSPEC_METHOD] = mtoken;
2680 values [MONO_METHODSPEC_SIGNATURE] = sig;
2683 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2690 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2692 MonoMethodInflated *imethod;
2695 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2699 g_assert (method->is_inflated);
2700 imethod = (MonoMethodInflated *) method;
2702 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2703 token = method_encode_methodspec (assembly, method);
2705 guint32 sig = method_encode_signature (
2706 assembly, mono_method_signature (imethod->declaring));
2707 token = mono_image_get_memberref_token (
2708 assembly, &method->klass->byval_arg, method->name, sig);
2711 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2716 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2718 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2721 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2722 token = mono_image_get_memberref_token (
2723 assembly, &m->klass->byval_arg, m->name, sig);
2729 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2731 MonoDynamicTable *table;
2739 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2740 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2741 * Because of this, we must not insert it into the `typeref' hash table.
2744 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2748 sigbuffer_init (&buf, 32);
2750 g_assert (tb->generic_params);
2751 klass = mono_class_from_mono_type (tb->type.type);
2753 if (tb->generic_container)
2754 mono_reflection_create_generic_class (tb);
2756 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2757 g_assert (klass->generic_container);
2758 sigbuffer_add_value (&buf, klass->byval_arg.type);
2759 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2761 count = mono_array_length (tb->generic_params);
2762 sigbuffer_add_value (&buf, count);
2763 for (i = 0; i < count; i++) {
2764 MonoReflectionGenericParam *gparam;
2766 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2768 encode_type (assembly, gparam->type.type, &buf);
2771 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2773 if (assembly->save) {
2774 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2775 alloc_table (table, table->rows + 1);
2776 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2777 values [MONO_TYPESPEC_SIGNATURE] = token;
2779 sigbuffer_free (&buf);
2781 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2782 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2788 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2790 MonoDynamicTable *table;
2793 guint32 token, pclass, parent, sig;
2796 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2800 klass = mono_class_from_mono_type (fb->typeb->type);
2801 name = mono_string_to_utf8 (fb->name);
2803 sig = fieldref_encode_signature (assembly, fb->type->type);
2805 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2806 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2808 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2809 parent >>= MONO_TYPEDEFORREF_BITS;
2811 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2813 if (assembly->save) {
2814 alloc_table (table, table->rows + 1);
2815 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2816 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2817 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2818 values [MONO_MEMBERREF_SIGNATURE] = sig;
2821 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2823 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2829 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2836 if (!assembly->save)
2839 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2840 g_assert (helper->type == 2);
2842 if (helper->arguments)
2843 nargs = mono_array_length (helper->arguments);
2847 size = 10 + (nargs * 10);
2849 sigbuffer_init (&buf, 32);
2851 /* Encode calling convention */
2852 /* Change Any to Standard */
2853 if ((helper->call_conv & 0x03) == 0x03)
2854 helper->call_conv = 0x01;
2855 /* explicit_this implies has_this */
2856 if (helper->call_conv & 0x40)
2857 helper->call_conv &= 0x20;
2859 if (helper->call_conv == 0) { /* Unmanaged */
2860 idx = helper->unmanaged_call_conv - 1;
2863 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2864 if (helper->call_conv & 0x02) /* varargs */
2868 sigbuffer_add_byte (&buf, idx);
2869 sigbuffer_add_value (&buf, nargs);
2870 encode_reflection_type (assembly, helper->return_type, &buf);
2871 for (i = 0; i < nargs; ++i) {
2872 MonoArray *modreqs = NULL;
2873 MonoArray *modopts = NULL;
2874 MonoReflectionType *pt;
2876 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
2877 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
2878 if (helper->modopts && (i < mono_array_length (helper->modopts)))
2879 modopts = mono_array_get (helper->modopts, MonoArray*, i);
2881 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
2882 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2883 encode_reflection_type (assembly, pt, &buf);
2885 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2886 sigbuffer_free (&buf);
2892 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2895 MonoDynamicTable *table;
2898 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2899 idx = table->next_idx ++;
2901 alloc_table (table, table->rows);
2902 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2904 values [MONO_STAND_ALONE_SIGNATURE] =
2905 mono_reflection_encode_sighelper (assembly, helper);
2911 reflection_cc_to_file (int call_conv) {
2912 switch (call_conv & 0x3) {
2914 case 1: return MONO_CALL_DEFAULT;
2915 case 2: return MONO_CALL_VARARG;
2917 g_assert_not_reached ();
2924 MonoMethodSignature *sig;
2930 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2935 MonoMethodSignature *sig;
2938 name = mono_string_to_utf8 (m->name);
2939 nparams = mono_array_length (m->parameters);
2940 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2942 sig->sentinelpos = -1;
2943 sig->call_convention = reflection_cc_to_file (m->call_conv);
2944 sig->param_count = nparams;
2945 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2946 for (i = 0; i < nparams; ++i) {
2947 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2948 sig->params [i] = t->type;
2951 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2953 if (strcmp (name, am->name) == 0 &&
2954 mono_metadata_type_equal (am->parent, m->parent->type) &&
2955 mono_metadata_signature_equal (am->sig, sig)) {
2958 m->table_idx = am->token & 0xffffff;
2962 am = g_new0 (ArrayMethod, 1);
2965 am->parent = m->parent->type;
2966 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2967 method_encode_signature (assembly, sig));
2968 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2969 m->table_idx = am->token & 0xffffff;
2974 * Insert into the metadata tables all the info about the TypeBuilder tb.
2975 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2978 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2980 MonoDynamicTable *table;
2982 int i, is_object = 0, is_system = 0;
2985 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2986 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2987 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2988 n = mono_string_to_utf8 (tb->name);
2989 if (strcmp (n, "Object") == 0)
2991 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2993 n = mono_string_to_utf8 (tb->nspace);
2994 if (strcmp (n, "System") == 0)
2996 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2998 if (tb->parent && !(is_system && is_object) &&
2999 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3000 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
3002 values [MONO_TYPEDEF_EXTENDS] = 0;
3004 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3005 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3008 * if we have explicitlayout or sequentiallayouts, output data in the
3009 * ClassLayout table.
3011 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3012 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3013 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3015 alloc_table (table, table->rows);
3016 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3017 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3018 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3019 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3022 /* handle interfaces */
3023 if (tb->interfaces) {
3024 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3026 table->rows += mono_array_length (tb->interfaces);
3027 alloc_table (table, table->rows);
3028 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3029 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3030 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3031 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3032 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3033 values += MONO_INTERFACEIMPL_SIZE;
3039 table = &assembly->tables [MONO_TABLE_FIELD];
3040 table->rows += tb->num_fields;
3041 alloc_table (table, table->rows);
3042 for (i = 0; i < tb->num_fields; ++i)
3043 mono_image_get_field_info (
3044 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3047 /* handle constructors */
3049 table = &assembly->tables [MONO_TABLE_METHOD];
3050 table->rows += mono_array_length (tb->ctors);
3051 alloc_table (table, table->rows);
3052 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3053 mono_image_get_ctor_info (domain,
3054 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3057 /* handle methods */
3059 table = &assembly->tables [MONO_TABLE_METHOD];
3060 table->rows += tb->num_methods;
3061 alloc_table (table, table->rows);
3062 for (i = 0; i < tb->num_methods; ++i)
3063 mono_image_get_method_info (
3064 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3067 /* Do the same with properties etc.. */
3068 if (tb->events && mono_array_length (tb->events)) {
3069 table = &assembly->tables [MONO_TABLE_EVENT];
3070 table->rows += mono_array_length (tb->events);
3071 alloc_table (table, table->rows);
3072 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3074 alloc_table (table, table->rows);
3075 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3076 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3077 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3078 for (i = 0; i < mono_array_length (tb->events); ++i)
3079 mono_image_get_event_info (
3080 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3082 if (tb->properties && mono_array_length (tb->properties)) {
3083 table = &assembly->tables [MONO_TABLE_PROPERTY];
3084 table->rows += mono_array_length (tb->properties);
3085 alloc_table (table, table->rows);
3086 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3088 alloc_table (table, table->rows);
3089 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3090 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3091 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3092 for (i = 0; i < mono_array_length (tb->properties); ++i)
3093 mono_image_get_property_info (
3094 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3097 /* handle generic parameters */
3098 if (tb->generic_params) {
3099 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3100 table->rows += mono_array_length (tb->generic_params);
3101 alloc_table (table, table->rows);
3102 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3103 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3105 mono_image_get_generic_param_info (
3106 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3110 mono_image_add_decl_security (assembly,
3111 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3114 MonoDynamicTable *ntable;
3116 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3117 ntable->rows += mono_array_length (tb->subtypes);
3118 alloc_table (ntable, ntable->rows);
3119 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3121 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3122 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3124 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3125 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3126 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3127 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3128 mono_string_to_utf8 (tb->name), tb->table_idx,
3129 ntable->next_idx, ntable->rows);*/
3130 values += MONO_NESTED_CLASS_SIZE;
3137 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3141 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3143 if (!type->subtypes)
3146 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3147 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3148 collect_types (types, subtype);
3153 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3155 if ((*type1)->table_idx < (*type2)->table_idx)
3158 if ((*type1)->table_idx > (*type2)->table_idx)
3165 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3170 for (i = 0; i < mono_array_length (pinfo); ++i) {
3171 MonoReflectionParamBuilder *pb;
3172 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3175 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3180 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3183 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3185 for (i = 0; i < tb->num_fields; ++i) {
3186 MonoReflectionFieldBuilder* fb;
3187 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3188 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3192 for (i = 0; i < mono_array_length (tb->events); ++i) {
3193 MonoReflectionEventBuilder* eb;
3194 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3195 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3198 if (tb->properties) {
3199 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3200 MonoReflectionPropertyBuilder* pb;
3201 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3202 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3206 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3207 MonoReflectionCtorBuilder* cb;
3208 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3209 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3210 params_add_cattrs (assembly, cb->pinfo);
3215 for (i = 0; i < tb->num_methods; ++i) {
3216 MonoReflectionMethodBuilder* mb;
3217 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3218 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3219 params_add_cattrs (assembly, mb->pinfo);
3224 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3225 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3230 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3234 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3236 if (moduleb->global_methods) {
3237 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3238 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3239 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3240 params_add_cattrs (assembly, mb->pinfo);
3244 if (moduleb->global_fields) {
3245 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3246 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3247 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3251 if (moduleb->types) {
3252 for (i = 0; i < moduleb->num_types; ++i)
3253 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3258 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3260 MonoDynamicTable *table;
3264 char *b = blob_size;
3267 table = &assembly->tables [MONO_TABLE_FILE];
3269 alloc_table (table, table->rows);
3270 values = table->values + table->next_idx * MONO_FILE_SIZE;
3271 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3272 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3273 if (module->image->dynamic) {
3274 /* This depends on the fact that the main module is emitted last */
3275 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3276 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3279 path = g_strdup (module->image->name);
3281 mono_sha1_get_digest_from_file (path, hash);
3284 mono_metadata_encode_value (20, b, &b);
3285 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3286 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3291 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3293 MonoDynamicTable *table;
3296 table = &assembly->tables [MONO_TABLE_MODULE];
3297 mb->table_idx = table->next_idx ++;
3298 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3299 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3302 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3303 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3304 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3305 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3309 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3310 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3312 MonoDynamicTable *table;
3316 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3317 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3320 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3322 alloc_table (table, table->rows);
3323 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3325 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3326 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3327 if (klass->nested_in)
3328 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3330 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3331 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3332 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3334 res = table->next_idx;
3338 /* Emit nested types */
3339 if (klass->nested_classes) {
3342 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3343 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3350 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3351 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3356 klass = mono_class_from_mono_type (tb->type.type);
3358 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3360 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3361 parent_index, assembly);
3365 * We need to do this ourselves since klass->nested_classes is not set up.
3368 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3369 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3374 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3375 guint32 module_index, MonoDynamicImage *assembly)
3377 MonoImage *image = module->image;
3381 t = &image->tables [MONO_TABLE_TYPEDEF];
3383 for (i = 0; i < t->rows; ++i) {
3384 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3386 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3387 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3392 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3394 MonoDynamicTable *table;
3400 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3402 if (assemblyb->type_forwarders) {
3403 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3404 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3410 klass = mono_class_from_mono_type (t->type);
3412 scope = resolution_scope_from_image (assembly, klass->image);
3413 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3414 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3417 alloc_table (table, table->rows);
3418 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3420 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3421 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3422 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3423 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3424 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3429 #define align_pointer(base,p)\
3431 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3433 (p) += 4 - (__diff & 3);\
3437 compare_constants (const void *a, const void *b)
3439 const guint32 *a_values = a;
3440 const guint32 *b_values = b;
3441 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3445 compare_semantics (const void *a, const void *b)
3447 const guint32 *a_values = a;
3448 const guint32 *b_values = b;
3449 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3452 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3456 compare_custom_attrs (const void *a, const void *b)
3458 const guint32 *a_values = a;
3459 const guint32 *b_values = b;
3461 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3465 compare_field_marshal (const void *a, const void *b)
3467 const guint32 *a_values = a;
3468 const guint32 *b_values = b;
3470 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3474 compare_nested (const void *a, const void *b)
3476 const guint32 *a_values = a;
3477 const guint32 *b_values = b;
3479 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3483 compare_genericparam (const void *a, const void *b)
3485 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3486 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3488 if ((*b_entry)->owner == (*a_entry)->owner)
3490 (*a_entry)->gparam->type.type->data.generic_param->num -
3491 (*b_entry)->gparam->type.type->data.generic_param->num;
3493 return (*a_entry)->owner - (*b_entry)->owner;
3497 compare_declsecurity_attrs (const void *a, const void *b)
3499 const guint32 *a_values = a;
3500 const guint32 *b_values = b;
3502 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3506 pad_heap (MonoDynamicStream *sh)
3508 if (sh->index & 3) {
3509 int sz = 4 - (sh->index & 3);
3510 memset (sh->data + sh->index, 0, sz);
3517 MonoDynamicStream *stream;
3521 * build_compressed_metadata() fills in the blob of data that represents the
3522 * raw metadata as it will be saved in the PE file. The five streams are output
3523 * and the metadata tables are comnpressed from the guint32 array representation,
3524 * to the compressed on-disk format.
3527 build_compressed_metadata (MonoDynamicImage *assembly)
3529 MonoDynamicTable *table;
3531 guint64 valid_mask = 0;
3532 guint64 sorted_mask;
3533 guint32 heapt_size = 0;
3534 guint32 meta_size = 256; /* allow for header and other stuff */
3535 guint32 table_offset;
3536 guint32 ntables = 0;
3542 struct StreamDesc stream_desc [5];
3544 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3545 for (i = 0; i < assembly->gen_params->len; i++){
3546 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3547 write_generic_param_entry (assembly, entry);
3550 stream_desc [0].name = "#~";
3551 stream_desc [0].stream = &assembly->tstream;
3552 stream_desc [1].name = "#Strings";
3553 stream_desc [1].stream = &assembly->sheap;
3554 stream_desc [2].name = "#US";
3555 stream_desc [2].stream = &assembly->us;
3556 stream_desc [3].name = "#Blob";
3557 stream_desc [3].stream = &assembly->blob;
3558 stream_desc [4].name = "#GUID";
3559 stream_desc [4].stream = &assembly->guid;
3561 /* tables that are sorted */
3562 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3563 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3564 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3565 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3566 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3567 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3569 /* Compute table sizes */
3570 /* the MonoImage has already been created in mono_image_basic_init() */
3571 meta = &assembly->image;
3573 /* sizes should be multiple of 4 */
3574 pad_heap (&assembly->blob);
3575 pad_heap (&assembly->guid);
3576 pad_heap (&assembly->sheap);
3577 pad_heap (&assembly->us);
3579 /* Setup the info used by compute_sizes () */
3580 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3581 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3582 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3584 meta_size += assembly->blob.index;
3585 meta_size += assembly->guid.index;
3586 meta_size += assembly->sheap.index;
3587 meta_size += assembly->us.index;
3589 for (i=0; i < MONO_TABLE_NUM; ++i)
3590 meta->tables [i].rows = assembly->tables [i].rows;
3592 for (i = 0; i < MONO_TABLE_NUM; i++){
3593 if (meta->tables [i].rows == 0)
3595 valid_mask |= (guint64)1 << i;
3597 meta->tables [i].row_size = mono_metadata_compute_size (
3598 meta, i, &meta->tables [i].size_bitfield);
3599 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3601 heapt_size += 24; /* #~ header size */
3602 heapt_size += ntables * 4;
3603 /* make multiple of 4 */
3606 meta_size += heapt_size;
3607 meta->raw_metadata = g_malloc0 (meta_size);
3608 p = (unsigned char*)meta->raw_metadata;
3609 /* the metadata signature */
3610 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3611 /* version numbers and 4 bytes reserved */
3612 int16val = (guint16*)p;
3613 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3614 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3616 /* version string */
3617 int32val = (guint32*)p;
3618 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3620 memcpy (p, meta->version, strlen (meta->version));
3621 p += GUINT32_FROM_LE (*int32val);
3622 align_pointer (meta->raw_metadata, p);
3623 int16val = (guint16*)p;
3624 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3625 *int16val = GUINT16_TO_LE (5); /* number of streams */
3629 * write the stream info.
3631 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3632 table_offset += 3; table_offset &= ~3;
3634 assembly->tstream.index = heapt_size;
3635 for (i = 0; i < 5; ++i) {
3636 int32val = (guint32*)p;
3637 stream_desc [i].stream->offset = table_offset;
3638 *int32val++ = GUINT32_TO_LE (table_offset);
3639 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3640 table_offset += GUINT32_FROM_LE (*int32val);
3641 table_offset += 3; table_offset &= ~3;
3643 strcpy ((char*)p, stream_desc [i].name);
3644 p += strlen (stream_desc [i].name) + 1;
3645 align_pointer (meta->raw_metadata, p);
3648 * now copy the data, the table stream header and contents goes first.
3650 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3651 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3652 int32val = (guint32*)p;
3653 *int32val = GUINT32_TO_LE (0); /* reserved */
3656 if (mono_get_runtime_info ()->framework_version [0] > '1') {
3657 *p++ = 2; /* version */
3660 *p++ = 1; /* version */
3664 if (meta->idx_string_wide)
3666 if (meta->idx_guid_wide)
3668 if (meta->idx_blob_wide)
3671 *p++ = 1; /* reserved */
3672 int64val = (guint64*)p;
3673 *int64val++ = GUINT64_TO_LE (valid_mask);
3674 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3676 int32val = (guint32*)p;
3677 for (i = 0; i < MONO_TABLE_NUM; i++){
3678 if (meta->tables [i].rows == 0)
3680 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3682 p = (unsigned char*)int32val;
3684 /* sort the tables that still need sorting */
3685 table = &assembly->tables [MONO_TABLE_CONSTANT];
3687 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3688 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3690 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3691 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3693 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3694 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3696 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3697 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3699 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3700 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3701 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3703 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3705 /* compress the tables */
3706 for (i = 0; i < MONO_TABLE_NUM; i++){
3709 guint32 bitfield = meta->tables [i].size_bitfield;
3710 if (!meta->tables [i].rows)
3712 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3713 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3714 meta->tables [i].base = (char*)p;
3715 for (row = 1; row <= meta->tables [i].rows; ++row) {
3716 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3717 for (col = 0; col < assembly->tables [i].columns; ++col) {
3718 switch (mono_metadata_table_size (bitfield, col)) {
3720 *p++ = values [col];
3723 *p++ = values [col] & 0xff;
3724 *p++ = (values [col] >> 8) & 0xff;
3727 *p++ = values [col] & 0xff;
3728 *p++ = (values [col] >> 8) & 0xff;
3729 *p++ = (values [col] >> 16) & 0xff;
3730 *p++ = (values [col] >> 24) & 0xff;
3733 g_assert_not_reached ();
3737 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3740 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3741 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3742 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3743 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3744 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3746 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3750 * Some tables in metadata need to be sorted according to some criteria, but
3751 * when methods and fields are first created with reflection, they may be assigned a token
3752 * that doesn't correspond to the final token they will get assigned after the sorting.
3753 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3754 * with the reflection objects that represent them. Once all the tables are set up, the
3755 * reflection objects will contains the correct table index. fixup_method() will fixup the
3756 * tokens for the method with ILGenerator @ilgen.
3759 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3761 guint32 code_idx = GPOINTER_TO_UINT (value);
3762 MonoReflectionILTokenInfo *iltoken;
3763 MonoReflectionFieldBuilder *field;
3764 MonoReflectionCtorBuilder *ctor;
3765 MonoReflectionMethodBuilder *method;
3766 MonoReflectionTypeBuilder *tb;
3767 MonoReflectionArrayMethod *am;
3769 unsigned char *target;
3771 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3772 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3773 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3774 switch (target [3]) {
3775 case MONO_TABLE_FIELD:
3776 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3777 field = (MonoReflectionFieldBuilder *)iltoken->member;
3778 idx = field->table_idx;
3779 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3780 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3781 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3783 g_assert_not_reached ();
3786 case MONO_TABLE_METHOD:
3787 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3788 method = (MonoReflectionMethodBuilder *)iltoken->member;
3789 idx = method->table_idx;
3790 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3791 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3792 idx = ctor->table_idx;
3793 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3794 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3795 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3796 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3798 g_assert_not_reached ();
3801 case MONO_TABLE_TYPEDEF:
3802 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3803 g_assert_not_reached ();
3804 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3805 idx = tb->table_idx;
3807 case MONO_TABLE_MEMBERREF:
3808 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3809 am = (MonoReflectionArrayMethod*)iltoken->member;
3810 idx = am->table_idx;
3811 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3812 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3813 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3814 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3815 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3816 g_assert (m->klass->generic_class || m->klass->generic_container);
3818 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3820 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3821 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3822 g_assert (f->generic_info);
3824 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3825 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3827 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3829 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
3831 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
3834 g_assert_not_reached ();
3837 case MONO_TABLE_METHODSPEC:
3838 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3839 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3840 g_assert (mono_method_signature (m)->generic_param_count);
3842 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3845 g_assert_not_reached ();
3849 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3851 target [0] = idx & 0xff;
3852 target [1] = (idx >> 8) & 0xff;
3853 target [2] = (idx >> 16) & 0xff;
3860 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3861 * value is not known when the table is emitted.
3864 fixup_cattrs (MonoDynamicImage *assembly)
3866 MonoDynamicTable *table;
3868 guint32 type, i, idx, token;
3871 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3873 for (i = 0; i < table->rows; ++i) {
3874 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3876 type = values [MONO_CUSTOM_ATTR_TYPE];
3877 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3878 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3879 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3880 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3883 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3884 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3885 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3886 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3893 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3895 MonoDynamicTable *table;
3898 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3900 alloc_table (table, table->rows);
3901 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3902 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3903 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3904 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3905 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3910 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3912 MonoDynamicTable *table;
3916 char *b = blob_size;
3918 guint32 idx, offset;
3920 if (rsrc->filename) {
3921 name = mono_string_to_utf8 (rsrc->filename);
3922 sname = g_path_get_basename (name);
3924 table = &assembly->tables [MONO_TABLE_FILE];
3926 alloc_table (table, table->rows);
3927 values = table->values + table->next_idx * MONO_FILE_SIZE;
3928 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3929 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3932 mono_sha1_get_digest_from_file (name, hash);
3933 mono_metadata_encode_value (20, b, &b);
3934 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3935 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3937 idx = table->next_idx++;
3939 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3945 data = mono_array_addr (rsrc->data, char, 0);
3946 len = mono_array_length (rsrc->data);
3952 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3953 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3954 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3955 mono_image_add_stream_data (&assembly->resources, data, len);
3959 * The entry should be emitted into the MANIFESTRESOURCE table of
3960 * the main module, but that needs to reference the FILE table
3961 * which isn't emitted yet.
3968 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3972 set_version_from_string (MonoString *version, guint32 *values)
3974 gchar *ver, *p, *str;
3977 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3978 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3979 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3980 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3983 ver = str = mono_string_to_utf8 (version);
3984 for (i = 0; i < 4; ++i) {
3985 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3991 /* handle Revision and Build */
4001 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4005 char *b = blob_size;
4010 len = mono_array_length (pkey);
4011 mono_metadata_encode_value (len, b, &b);
4012 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4013 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4015 assembly->public_key = g_malloc (len);
4016 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4017 assembly->public_key_len = len;
4019 /* Special case: check for ECMA key (16 bytes) */
4020 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4021 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4022 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4023 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4024 /* minimum key size (in 2.0) is 384 bits */
4025 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4027 /* FIXME - verifier */
4028 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4029 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4031 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4037 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4039 MonoDynamicTable *table;
4040 MonoDynamicImage *assembly;
4041 MonoReflectionAssemblyBuilder *assemblyb;
4045 guint32 module_index;
4047 assemblyb = moduleb->assemblyb;
4048 assembly = moduleb->dynamic_image;
4049 domain = mono_object_domain (assemblyb);
4051 /* Emit ASSEMBLY table */
4052 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4053 alloc_table (table, 1);
4054 values = table->values + MONO_ASSEMBLY_SIZE;
4055 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4056 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4057 if (assemblyb->culture) {
4058 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4060 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4062 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4063 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4064 set_version_from_string (assemblyb->version, values);
4066 /* Emit FILE + EXPORTED_TYPE table */
4068 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4070 MonoReflectionModuleBuilder *file_module =
4071 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4072 if (file_module != moduleb) {
4073 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4075 if (file_module->types) {
4076 for (j = 0; j < file_module->num_types; ++j) {
4077 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4078 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4083 if (assemblyb->loaded_modules) {
4084 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4085 MonoReflectionModule *file_module =
4086 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4087 mono_image_fill_file_table (domain, file_module, assembly);
4089 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4092 if (assemblyb->type_forwarders)
4093 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4095 /* Emit MANIFESTRESOURCE table */
4097 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4099 MonoReflectionModuleBuilder *file_module =
4100 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4101 /* The table for the main module is emitted later */
4102 if (file_module != moduleb) {
4104 if (file_module->resources) {
4105 int len = mono_array_length (file_module->resources);
4106 for (j = 0; j < len; ++j) {
4107 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4108 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4116 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4117 * for the modulebuilder @moduleb.
4118 * At the end of the process, method and field tokens are fixed up and the
4119 * on-disk compressed metadata representation is created.
4122 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4124 MonoDynamicTable *table;
4125 MonoDynamicImage *assembly;
4126 MonoReflectionAssemblyBuilder *assemblyb;
4132 assemblyb = moduleb->assemblyb;
4133 assembly = moduleb->dynamic_image;
4134 domain = mono_object_domain (assemblyb);
4136 if (assembly->text_rva)
4139 assembly->text_rva = START_TEXT_RVA;
4141 if (moduleb->is_main) {
4142 mono_image_emit_manifest (moduleb);
4145 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4146 table->rows = 1; /* .<Module> */
4148 alloc_table (table, table->rows);
4150 * Set the first entry.
4152 values = table->values + table->columns;
4153 values [MONO_TYPEDEF_FLAGS] = 0;
4154 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4155 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4156 values [MONO_TYPEDEF_EXTENDS] = 0;
4157 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4158 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4161 * handle global methods
4162 * FIXME: test what to do when global methods are defined in multiple modules.
4164 if (moduleb->global_methods) {
4165 table = &assembly->tables [MONO_TABLE_METHOD];
4166 table->rows += mono_array_length (moduleb->global_methods);
4167 alloc_table (table, table->rows);
4168 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4169 mono_image_get_method_info (
4170 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4172 if (moduleb->global_fields) {
4173 table = &assembly->tables [MONO_TABLE_FIELD];
4174 table->rows += mono_array_length (moduleb->global_fields);
4175 alloc_table (table, table->rows);
4176 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4177 mono_image_get_field_info (
4178 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4181 table = &assembly->tables [MONO_TABLE_MODULE];
4182 alloc_table (table, 1);
4183 mono_image_fill_module_table (domain, moduleb, assembly);
4185 /* Collect all types into a list sorted by their table_idx */
4186 types = g_ptr_array_new ();
4189 for (i = 0; i < moduleb->num_types; ++i) {
4190 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4191 collect_types (types, type);
4194 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4195 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4196 table->rows += types->len;
4197 alloc_table (table, table->rows);
4200 * Emit type names + namespaces at one place inside the string heap,
4201 * so load_class_names () needs to touch fewer pages.
4203 for (i = 0; i < types->len; ++i) {
4204 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4205 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4207 for (i = 0; i < types->len; ++i) {
4208 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4209 string_heap_insert_mstring (&assembly->sheap, tb->name);
4212 for (i = 0; i < types->len; ++i) {
4213 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4214 mono_image_get_type_info (domain, type, assembly);
4218 * table->rows is already set above and in mono_image_fill_module_table.
4220 /* add all the custom attributes at the end, once all the indexes are stable */
4221 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4223 /* CAS assembly permissions */
4224 if (assemblyb->permissions_minimum)
4225 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4226 if (assemblyb->permissions_optional)
4227 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4228 if (assemblyb->permissions_refused)
4229 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4231 module_add_cattrs (assembly, moduleb);
4234 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4236 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4237 * the final tokens and don't need another fixup pass. */
4239 if (moduleb->global_methods) {
4240 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4241 MonoReflectionMethodBuilder *mb = mono_array_get (
4242 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4243 mono_image_add_methodimpl (assembly, mb);
4247 for (i = 0; i < types->len; ++i) {
4248 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4249 if (type->methods) {
4250 for (j = 0; j < type->num_methods; ++j) {
4251 MonoReflectionMethodBuilder *mb = mono_array_get (
4252 type->methods, MonoReflectionMethodBuilder*, j);
4254 mono_image_add_methodimpl (assembly, mb);
4259 g_ptr_array_free (types, TRUE);
4261 fixup_cattrs (assembly);
4265 * mono_image_insert_string:
4266 * @module: module builder object
4269 * Insert @str into the user string stream of @module.
4272 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4274 MonoDynamicImage *assembly;
4279 MONO_ARCH_SAVE_REGS;
4281 if (!module->dynamic_image)
4282 mono_image_module_basic_init (module);
4284 assembly = module->dynamic_image;
4286 if (assembly->save) {
4287 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4288 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4289 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4291 char *swapped = g_malloc (2 * mono_string_length (str));
4292 const char *p = (const char*)mono_string_chars (str);
4294 swap_with_size (swapped, p, 2, mono_string_length (str));
4295 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4299 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4301 mono_image_add_stream_data (&assembly->us, "", 1);
4303 idx = assembly->us.index ++;
4306 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4308 return MONO_TOKEN_STRING | idx;
4312 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4317 klass = obj->vtable->klass;
4318 if (strcmp (klass->name, "MonoMethod") == 0) {
4319 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4320 MonoMethodSignature *sig, *old;
4321 guint32 sig_token, parent;
4324 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4326 nargs = mono_array_length (opt_param_types);
4327 old = mono_method_signature (method);
4328 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4330 sig->hasthis = old->hasthis;
4331 sig->explicit_this = old->explicit_this;
4332 sig->call_convention = old->call_convention;
4333 sig->generic_param_count = old->generic_param_count;
4334 sig->param_count = old->param_count + nargs;
4335 sig->sentinelpos = old->param_count;
4336 sig->ret = old->ret;
4338 for (i = 0; i < old->param_count; i++)
4339 sig->params [i] = old->params [i];
4341 for (i = 0; i < nargs; i++) {
4342 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4343 sig->params [old->param_count + i] = rt->type;
4346 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4347 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4348 parent >>= MONO_TYPEDEFORREF_BITS;
4350 parent <<= MONO_MEMBERREF_PARENT_BITS;
4351 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4353 sig_token = method_encode_signature (assembly, sig);
4354 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4355 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4356 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4357 ReflectionMethodBuilder rmb;
4358 guint32 parent, sig;
4361 reflection_methodbuilder_from_method_builder (&rmb, mb);
4362 rmb.opt_types = opt_param_types;
4364 sig = method_builder_encode_signature (assembly, &rmb);
4366 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4367 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4369 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4370 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4372 name = mono_string_to_utf8 (rmb.name);
4373 token = mono_image_get_varargs_method_token (
4374 assembly, parent, name, sig);
4377 g_error ("requested method token for %s\n", klass->name);
4384 * mono_image_create_token:
4385 * @assembly: a dynamic assembly
4387 * @register_token: Whenever to register the token in the assembly->tokens hash.
4389 * Get a token to insert in the IL code stream for the given MemberInfo.
4390 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4391 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4395 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4396 gboolean create_methodspec, gboolean register_token)
4401 klass = obj->vtable->klass;
4402 if (strcmp (klass->name, "MethodBuilder") == 0) {
4403 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4404 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4406 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4407 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4409 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4410 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4411 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4412 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4413 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4415 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4416 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4418 token = mono_image_get_ctorbuilder_token (assembly, mb);
4419 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4420 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4421 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4422 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4423 if (tb->generic_params) {
4424 token = mono_image_get_generic_field_token (assembly, fb);
4426 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4428 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4429 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4430 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4431 } else if (strcmp (klass->name, "MonoType") == 0) {
4432 MonoReflectionType *tb = (MonoReflectionType *)obj;
4433 MonoClass *mc = mono_class_from_mono_type (tb->type);
4434 token = mono_metadata_token_from_dor (
4435 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4436 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4437 MonoReflectionType *tb = (MonoReflectionType *)obj;
4438 token = mono_metadata_token_from_dor (
4439 mono_image_typedef_or_ref (assembly, tb->type));
4440 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4441 MonoReflectionType *tb = (MonoReflectionType *)obj;
4442 token = mono_metadata_token_from_dor (
4443 mono_image_typedef_or_ref (assembly, tb->type));
4444 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4445 strcmp (klass->name, "MonoMethod") == 0 ||
4446 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4447 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4448 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4449 if (m->method->is_inflated) {
4450 if (create_methodspec)
4451 token = mono_image_get_methodspec_token (assembly, m->method);
4453 token = mono_image_get_inflated_method_token (assembly, m->method);
4454 } else if ((m->method->klass->image == &assembly->image) &&
4455 !m->method->klass->generic_class) {
4456 static guint32 method_table_idx = 0xffffff;
4457 if (m->method->klass->wastypebuilder) {
4458 /* we use the same token as the one that was assigned
4459 * to the Methodbuilder.
4460 * FIXME: do the equivalent for Fields.
4462 token = m->method->token;
4465 * Each token should have a unique index, but the indexes are
4466 * assigned by managed code, so we don't know about them. An
4467 * easy solution is to count backwards...
4469 method_table_idx --;
4470 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4473 token = mono_image_get_methodref_token (assembly, m->method);
4475 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4476 } else if (strcmp (klass->name, "MonoField") == 0) {
4477 MonoReflectionField *f = (MonoReflectionField *)obj;
4478 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4479 static guint32 field_table_idx = 0xffffff;
4481 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4483 token = mono_image_get_fieldref_token (assembly, f);
4485 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4486 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4487 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4488 token = mono_image_get_array_token (assembly, m);
4489 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4490 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4491 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4492 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4493 MonoReflectionType *tb = (MonoReflectionType *)obj;
4494 token = mono_metadata_token_from_dor (
4495 mono_image_typedef_or_ref (assembly, tb->type));
4496 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4497 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4498 token = mono_image_get_field_on_inst_token (assembly, f);
4499 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4500 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4501 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4502 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4503 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4504 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4506 g_error ("requested token for %s\n", klass->name);
4510 mono_image_register_token (assembly, token, obj);
4516 * mono_image_register_token:
4518 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4519 * the Module.ResolveXXXToken () methods to work.
4522 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4524 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4526 /* There could be multiple MethodInfo objects with the same token */
4527 //g_assert (prev == obj);
4529 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4534 guint32 import_lookup_table;
4538 guint32 import_address_table_rva;
4546 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4548 static MonoDynamicImage*
4549 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4551 static const guchar entrycode [16] = {0xff, 0x25, 0};
4552 MonoDynamicImage *image;
4555 const char *version;
4557 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4558 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4560 version = mono_get_runtime_info ()->runtime_version;
4563 image = GC_MALLOC (sizeof (MonoDynamicImage));
4565 image = g_new0 (MonoDynamicImage, 1);
4568 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4570 /*g_print ("created image %p\n", image);*/
4571 /* keep in sync with image.c */
4572 image->image.name = assembly_name;
4573 image->image.assembly_name = image->image.name; /* they may be different */
4574 image->image.module_name = module_name;
4575 image->image.version = g_strdup (version);
4576 image->image.md_version_major = 1;
4577 image->image.md_version_minor = 1;
4578 image->image.dynamic = TRUE;
4580 image->image.references = g_new0 (MonoAssembly*, 1);
4581 image->image.references [0] = NULL;
4583 mono_image_init (&image->image);
4585 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4586 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4587 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4588 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4589 image->handleref = g_hash_table_new (NULL, NULL);
4590 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4591 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4592 image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4593 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4594 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4595 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4596 image->gen_params = g_ptr_array_new ();
4598 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4599 string_heap_init (&image->sheap);
4600 mono_image_add_stream_data (&image->us, "", 1);
4601 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4602 /* import tables... */
4603 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4604 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4605 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4606 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4607 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4608 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4609 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4610 stream_data_align (&image->code);
4612 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4614 for (i=0; i < MONO_TABLE_NUM; ++i) {
4615 image->tables [i].next_idx = 1;
4616 image->tables [i].columns = table_sizes [i];
4619 image->image.assembly = (MonoAssembly*)assembly;
4620 image->run = assembly->run;
4621 image->save = assembly->save;
4622 image->pe_kind = 0x1; /* ILOnly */
4623 image->machine = 0x14c; /* I386 */
4625 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4631 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4637 mono_dynamic_image_free (MonoDynamicImage *image)
4639 MonoDynamicImage *di = image;
4644 mono_g_hash_table_destroy (di->methodspec);
4646 g_hash_table_destroy (di->typespec);
4648 g_hash_table_destroy (di->typeref);
4650 g_hash_table_destroy (di->handleref);
4652 mono_g_hash_table_destroy (di->tokens);
4653 if (di->generic_def_objects)
4654 mono_g_hash_table_destroy (di->generic_def_objects);
4655 if (di->blob_cache) {
4656 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4657 g_hash_table_destroy (di->blob_cache);
4659 for (list = di->array_methods; list; list = list->next) {
4660 ArrayMethod *am = (ArrayMethod *)list->data;
4665 g_list_free (di->array_methods);
4666 if (di->gen_params) {
4667 for (i = 0; i < di->gen_params->len; i++) {
4668 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4669 if (entry->gparam->type.type) {
4670 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4671 g_free ((char*)param->name);
4673 g_free (entry->gparam->type.type);
4677 g_ptr_array_free (di->gen_params, TRUE);
4679 if (di->token_fixups)
4680 mono_g_hash_table_destroy (di->token_fixups);
4681 if (di->method_to_table_idx)
4682 g_hash_table_destroy (di->method_to_table_idx);
4683 if (di->field_to_table_idx)
4684 g_hash_table_destroy (di->field_to_table_idx);
4685 if (di->method_aux_hash)
4686 g_hash_table_destroy (di->method_aux_hash);
4687 g_free (di->strong_name);
4688 g_free (di->win32_res);
4690 g_free (di->public_key);
4692 /*g_print ("string heap destroy for image %p\n", di);*/
4693 mono_dynamic_stream_reset (&di->sheap);
4694 mono_dynamic_stream_reset (&di->code);
4695 mono_dynamic_stream_reset (&di->resources);
4696 mono_dynamic_stream_reset (&di->us);
4697 mono_dynamic_stream_reset (&di->blob);
4698 mono_dynamic_stream_reset (&di->tstream);
4699 mono_dynamic_stream_reset (&di->guid);
4700 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4701 g_free (di->tables [i].values);
4706 * mono_image_basic_init:
4707 * @assembly: an assembly builder object
4709 * Create the MonoImage that represents the assembly builder and setup some
4710 * of the helper hash table and the basic metadata streams.
4713 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4715 MonoDynamicAssembly *assembly;
4716 MonoDynamicImage *image;
4717 MonoDomain *domain = mono_object_domain (assemblyb);
4719 MONO_ARCH_SAVE_REGS;
4721 if (assemblyb->dynamic_assembly)
4725 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4727 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4730 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4732 assembly->assembly.ref_count = 1;
4733 assembly->assembly.dynamic = TRUE;
4734 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4735 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4736 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4737 if (assemblyb->culture)
4738 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4740 assembly->assembly.aname.culture = g_strdup ("");
4742 if (assemblyb->version) {
4743 char *vstr = mono_string_to_utf8 (assemblyb->version);
4744 char **version = g_strsplit (vstr, ".", 4);
4745 char **parts = version;
4746 assembly->assembly.aname.major = atoi (*parts++);
4747 assembly->assembly.aname.minor = atoi (*parts++);
4748 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4749 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4751 g_strfreev (version);
4754 assembly->assembly.aname.major = 0;
4755 assembly->assembly.aname.minor = 0;
4756 assembly->assembly.aname.build = 0;
4757 assembly->assembly.aname.revision = 0;
4760 assembly->run = assemblyb->access != 2;
4761 assembly->save = assemblyb->access != 1;
4763 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4764 image->initial_image = TRUE;
4765 assembly->assembly.aname.name = image->image.name;
4766 assembly->assembly.image = &image->image;
4768 mono_domain_assemblies_lock (domain);
4769 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4770 mono_domain_assemblies_unlock (domain);
4772 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4774 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4776 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4780 calc_section_size (MonoDynamicImage *assembly)
4784 /* alignment constraints */
4785 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4786 g_assert ((assembly->code.index % 4) == 0);
4787 assembly->meta_size += 3;
4788 assembly->meta_size &= ~3;
4789 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4790 g_assert ((assembly->resources.index % 4) == 0);
4792 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4793 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4796 if (assembly->win32_res) {
4797 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4799 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4800 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4804 assembly->sections [MONO_SECTION_RELOC].size = 12;
4805 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4815 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4819 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4821 ResTreeNode *t1 = (ResTreeNode*)a;
4822 ResTreeNode *t2 = (ResTreeNode*)b;
4824 return t1->id - t2->id;
4828 * resource_tree_create:
4830 * Organize the resources into a resource tree.
4832 static ResTreeNode *
4833 resource_tree_create (MonoArray *win32_resources)
4835 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4839 tree = g_new0 (ResTreeNode, 1);
4841 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4842 MonoReflectionWin32Resource *win32_res =
4843 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4847 /* FIXME: BUG: this stores managed references in unmanaged memory */
4848 lang_node = g_new0 (ResTreeNode, 1);
4849 lang_node->id = win32_res->lang_id;
4850 lang_node->win32_res = win32_res;
4852 /* Create type node if neccesary */
4854 for (l = tree->children; l; l = l->next)
4855 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4856 type_node = (ResTreeNode*)l->data;
4861 type_node = g_new0 (ResTreeNode, 1);
4862 type_node->id = win32_res->res_type;
4865 * The resource types have to be sorted otherwise
4866 * Windows Explorer can't display the version information.
4868 tree->children = g_slist_insert_sorted (tree->children,
4869 type_node, resource_tree_compare_by_id);
4872 /* Create res node if neccesary */
4874 for (l = type_node->children; l; l = l->next)
4875 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4876 res_node = (ResTreeNode*)l->data;
4881 res_node = g_new0 (ResTreeNode, 1);
4882 res_node->id = win32_res->res_id;
4883 type_node->children = g_slist_append (type_node->children, res_node);
4886 res_node->children = g_slist_append (res_node->children, lang_node);
4893 * resource_tree_encode:
4895 * Encode the resource tree into the format used in the PE file.
4898 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4901 MonoPEResourceDir dir;
4902 MonoPEResourceDirEntry dir_entry;
4903 MonoPEResourceDataEntry data_entry;
4907 * For the format of the resource directory, see the article
4908 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4912 memset (&dir, 0, sizeof (dir));
4913 memset (&dir_entry, 0, sizeof (dir_entry));
4914 memset (&data_entry, 0, sizeof (data_entry));
4916 g_assert (sizeof (dir) == 16);
4917 g_assert (sizeof (dir_entry) == 8);
4918 g_assert (sizeof (data_entry) == 16);
4920 node->offset = p - begin;
4922 /* IMAGE_RESOURCE_DIRECTORY */
4923 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4925 memcpy (p, &dir, sizeof (dir));
4928 /* Reserve space for entries */
4930 p += sizeof (dir_entry) * dir.res_id_entries;
4932 /* Write children */
4933 for (l = node->children; l; l = l->next) {
4934 ResTreeNode *child = (ResTreeNode*)l->data;
4936 if (child->win32_res) {
4938 child->offset = p - begin;
4940 /* IMAGE_RESOURCE_DATA_ENTRY */
4941 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4942 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4944 memcpy (p, &data_entry, sizeof (data_entry));
4945 p += sizeof (data_entry);
4947 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4948 p += data_entry.rde_size;
4950 resource_tree_encode (child, begin, p, &p);
4954 /* IMAGE_RESOURCE_ENTRY */
4955 for (l = node->children; l; l = l->next) {
4956 ResTreeNode *child = (ResTreeNode*)l->data;
4957 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4959 dir_entry.is_dir = child->win32_res ? 0 : 1;
4960 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4962 memcpy (entries, &dir_entry, sizeof (dir_entry));
4963 entries += sizeof (dir_entry);
4970 resource_tree_free (ResTreeNode * node)
4973 for (list = node->children; list; list = list->next)
4974 resource_tree_free ((ResTreeNode*)list->data);
4975 g_slist_free(node->children);
4980 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4985 MonoReflectionWin32Resource *win32_res;
4988 if (!assemblyb->win32_resources)
4992 * Resources are stored in a three level tree inside the PE file.
4993 * - level one contains a node for each type of resource
4994 * - level two contains a node for each resource
4995 * - level three contains a node for each instance of a resource for a
4996 * specific language.
4999 tree = resource_tree_create (assemblyb->win32_resources);
5001 /* Estimate the size of the encoded tree */
5003 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5004 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5005 size += mono_array_length (win32_res->res_data);
5007 /* Directory structure */
5008 size += mono_array_length (assemblyb->win32_resources) * 256;
5009 p = buf = g_malloc (size);
5011 resource_tree_encode (tree, p, p, &p);
5013 g_assert (p - buf <= size);
5015 assembly->win32_res = g_malloc (p - buf);
5016 assembly->win32_res_size = p - buf;
5017 memcpy (assembly->win32_res, buf, p - buf);
5020 resource_tree_free (tree);
5024 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5026 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5029 p += sizeof (MonoPEResourceDir);
5030 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
5031 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5032 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
5033 if (dir_entry->is_dir) {
5034 fixup_resource_directory (res_section, child, rva);
5036 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5037 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5040 p += sizeof (MonoPEResourceDirEntry);
5045 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5048 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5049 g_error ("WriteFile returned %d\n", GetLastError ());
5053 * mono_image_create_pefile:
5054 * @mb: a module builder object
5056 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5057 * assembly->pefile where it can be easily retrieved later in chunks.
5060 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
5061 MonoMSDOSHeader *msdos;
5062 MonoDotNetHeader *header;
5063 MonoSectionTable *section;
5064 MonoCLIHeader *cli_header;
5065 guint32 size, image_size, virtual_base, text_offset;
5066 guint32 header_start, section_start, file_offset, virtual_offset;
5067 MonoDynamicImage *assembly;
5068 MonoReflectionAssemblyBuilder *assemblyb;
5069 MonoDynamicStream pefile_stream = {0};
5070 MonoDynamicStream *pefile = &pefile_stream;
5072 guint32 *rva, value;
5074 static const unsigned char msheader[] = {
5075 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5076 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5077 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5078 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5079 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5080 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5081 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5082 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5085 assemblyb = mb->assemblyb;
5087 mono_image_basic_init (assemblyb);
5088 assembly = mb->dynamic_image;
5090 assembly->pe_kind = assemblyb->pe_kind;
5091 assembly->machine = assemblyb->machine;
5092 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5093 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5095 mono_image_build_metadata (mb);
5097 if (mb->is_main && assemblyb->resources) {
5098 int len = mono_array_length (assemblyb->resources);
5099 for (i = 0; i < len; ++i)
5100 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5103 if (mb->resources) {
5104 int len = mono_array_length (mb->resources);
5105 for (i = 0; i < len; ++i)
5106 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5109 build_compressed_metadata (assembly);
5112 assembly_add_win32_resources (assembly, assemblyb);
5114 nsections = calc_section_size (assembly);
5116 /* The DOS header and stub */
5117 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5118 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5120 /* the dotnet header */
5121 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5123 /* the section tables */
5124 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5126 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5127 virtual_offset = VIRT_ALIGN;
5130 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5131 if (!assembly->sections [i].size)
5134 file_offset += FILE_ALIGN - 1;
5135 file_offset &= ~(FILE_ALIGN - 1);
5136 virtual_offset += VIRT_ALIGN - 1;
5137 virtual_offset &= ~(VIRT_ALIGN - 1);
5139 assembly->sections [i].offset = file_offset;
5140 assembly->sections [i].rva = virtual_offset;
5142 file_offset += assembly->sections [i].size;
5143 virtual_offset += assembly->sections [i].size;
5144 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5147 file_offset += FILE_ALIGN - 1;
5148 file_offset &= ~(FILE_ALIGN - 1);
5150 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5152 /* back-patch info */
5153 msdos = (MonoMSDOSHeader*)pefile->data;
5154 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5156 header = (MonoDotNetHeader*)(pefile->data + header_start);
5157 header->pesig [0] = 'P';
5158 header->pesig [1] = 'E';
5160 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5161 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5162 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5163 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5164 if (assemblyb->pekind == 1) {
5166 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5169 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5172 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5174 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5175 header->pe.pe_major = 6;
5176 header->pe.pe_minor = 0;
5177 size = assembly->sections [MONO_SECTION_TEXT].size;
5178 size += FILE_ALIGN - 1;
5179 size &= ~(FILE_ALIGN - 1);
5180 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5181 size = assembly->sections [MONO_SECTION_RSRC].size;
5182 size += FILE_ALIGN - 1;
5183 size &= ~(FILE_ALIGN - 1);
5184 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5185 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5186 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5187 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5188 /* pe_rva_entry_point always at the beginning of the text section */
5189 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5191 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5192 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5193 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5194 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5195 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5196 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5197 size = section_start;
5198 size += FILE_ALIGN - 1;
5199 size &= ~(FILE_ALIGN - 1);
5200 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5202 size += VIRT_ALIGN - 1;
5203 size &= ~(VIRT_ALIGN - 1);
5204 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5207 // Translate the PEFileKind value to the value expected by the Windows loader
5213 // PEFileKinds.Dll == 1
5214 // PEFileKinds.ConsoleApplication == 2
5215 // PEFileKinds.WindowApplication == 3
5218 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5219 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5221 if (assemblyb->pekind == 3)
5226 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5228 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5229 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5230 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5231 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5232 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5233 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5235 /* fill data directory entries */
5237 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5238 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5240 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5241 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5243 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5244 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5245 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5246 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5247 /* patch entrypoint name */
5248 if (assemblyb->pekind == 1)
5249 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5251 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5252 /* patch imported function RVA name */
5253 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5254 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5256 /* the import table */
5257 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5258 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5259 /* patch imported dll RVA name and other entries in the dir */
5260 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5261 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5262 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5263 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5264 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5265 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5267 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5268 value = (assembly->text_rva + assembly->imp_names_offset);
5269 *p++ = (value) & 0xff;
5270 *p++ = (value >> 8) & (0xff);
5271 *p++ = (value >> 16) & (0xff);
5272 *p++ = (value >> 24) & (0xff);
5274 /* the CLI header info */
5275 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5276 cli_header->ch_size = GUINT32_FROM_LE (72);
5277 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5278 if (mono_get_runtime_info ()->framework_version [0] > '1')
5279 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5281 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5282 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5283 if (assemblyb->entry_point) {
5284 guint32 table_idx = 0;
5285 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5286 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5287 table_idx = methodb->table_idx;
5289 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5291 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5293 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5295 /* The embedded managed resources */
5296 text_offset = assembly->text_rva + assembly->code.index;
5297 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5298 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5299 text_offset += assembly->resources.index;
5300 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5301 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5302 text_offset += assembly->meta_size;
5303 if (assembly->strong_name_size) {
5304 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5305 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5306 text_offset += assembly->strong_name_size;
5309 /* write the section tables and section content */
5310 section = (MonoSectionTable*)(pefile->data + section_start);
5311 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5312 static const char section_names [][7] = {
5313 ".text", ".rsrc", ".reloc"
5315 if (!assembly->sections [i].size)
5317 strcpy (section->st_name, section_names [i]);
5318 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5319 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5320 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5321 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5322 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5323 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5324 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5328 checked_write_file (file, pefile->data, pefile->index);
5330 mono_dynamic_stream_reset (pefile);
5332 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5333 if (!assembly->sections [i].size)
5336 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5337 g_error ("SetFilePointer returned %d\n", GetLastError ());
5340 case MONO_SECTION_TEXT:
5341 /* patch entry point */
5342 p = (guchar*)(assembly->code.data + 2);
5343 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5344 *p++ = (value) & 0xff;
5345 *p++ = (value >> 8) & 0xff;
5346 *p++ = (value >> 16) & 0xff;
5347 *p++ = (value >> 24) & 0xff;
5349 checked_write_file (file, assembly->code.data, assembly->code.index);
5350 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5351 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5352 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5355 g_free (assembly->image.raw_metadata);
5357 case MONO_SECTION_RELOC: {
5361 guint16 type_and_offset;
5365 g_assert (sizeof (reloc) == 12);
5367 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5368 reloc.block_size = GUINT32_FROM_LE (12);
5371 * the entrypoint is always at the start of the text section
5372 * 3 is IMAGE_REL_BASED_HIGHLOW
5373 * 2 is patch_size_rva - text_rva
5375 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5378 checked_write_file (file, &reloc, sizeof (reloc));
5382 case MONO_SECTION_RSRC:
5383 if (assembly->win32_res) {
5385 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5386 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5387 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5391 g_assert_not_reached ();
5395 /* check that the file is properly padded */
5396 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5397 g_error ("SetFilePointer returned %d\n", GetLastError ());
5398 if (! SetEndOfFile (file))
5399 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5401 mono_dynamic_stream_reset (&assembly->code);
5402 mono_dynamic_stream_reset (&assembly->us);
5403 mono_dynamic_stream_reset (&assembly->blob);
5404 mono_dynamic_stream_reset (&assembly->guid);
5405 mono_dynamic_stream_reset (&assembly->sheap);
5407 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5408 g_hash_table_destroy (assembly->blob_cache);
5409 assembly->blob_cache = NULL;
5412 MonoReflectionModule *
5413 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5417 MonoImageOpenStatus status;
5418 MonoDynamicAssembly *assembly;
5419 guint32 module_count;
5420 MonoImage **new_modules;
5421 gboolean *new_modules_loaded;
5423 name = mono_string_to_utf8 (fileName);
5425 image = mono_image_open (name, &status);
5428 if (status == MONO_IMAGE_ERROR_ERRNO)
5429 exc = mono_get_exception_file_not_found (fileName);
5431 exc = mono_get_exception_bad_image_format (name);
5433 mono_raise_exception (exc);
5438 assembly = ab->dynamic_assembly;
5439 image->assembly = (MonoAssembly*)assembly;
5441 module_count = image->assembly->image->module_count;
5442 new_modules = g_new0 (MonoImage *, module_count + 1);
5443 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5445 if (image->assembly->image->modules)
5446 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5447 if (image->assembly->image->modules_loaded)
5448 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5449 new_modules [module_count] = image;
5450 new_modules_loaded [module_count] = TRUE;
5451 mono_image_addref (image);
5453 g_free (image->assembly->image->modules);
5454 image->assembly->image->modules = new_modules;
5455 image->assembly->image->modules_loaded = new_modules_loaded;
5456 image->assembly->image->module_count ++;
5458 mono_assembly_load_references (image, &status);
5460 mono_image_close (image);
5461 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5464 return mono_module_get_object (mono_domain_get (), image);
5468 * We need to return always the same object for MethodInfo, FieldInfo etc..
5469 * but we need to consider the reflected type.
5470 * type uses a different hash, since it uses custom hash/equal functions.
5475 MonoClass *refclass;
5479 reflected_equal (gconstpointer a, gconstpointer b) {
5480 const ReflectedEntry *ea = a;
5481 const ReflectedEntry *eb = b;
5483 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5487 reflected_hash (gconstpointer a) {
5488 const ReflectedEntry *ea = a;
5489 return mono_aligned_addr_hash (ea->item);
5492 #define CHECK_OBJECT(t,p,k) \
5498 mono_domain_lock (domain); \
5499 if (!domain->refobject_hash) \
5500 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5501 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5502 mono_domain_unlock (domain); \
5505 mono_domain_unlock (domain); \
5508 #ifndef HAVE_NULL_GC
5509 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5511 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5514 #define CACHE_OBJECT(t,p,o,k) \
5517 ReflectedEntry pe; \
5519 pe.refclass = (k); \
5520 mono_domain_lock (domain); \
5521 if (!domain->refobject_hash) \
5522 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5523 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5525 ReflectedEntry *e = ALLOC_REFENTRY; \
5527 e->refclass = (k); \
5528 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5531 mono_domain_unlock (domain); \
5536 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5538 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5542 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5544 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5548 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5550 MonoDynamicImage *image = moduleb->dynamic_image;
5551 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5554 MonoImage **new_modules;
5557 * FIXME: we already created an image in mono_image_basic_init (), but
5558 * we don't know which module it belongs to, since that is only
5559 * determined at assembly save time.
5561 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5562 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5564 moduleb->module.image = &image->image;
5565 moduleb->dynamic_image = image;
5566 register_module (mono_object_domain (moduleb), moduleb, image);
5568 /* register the module with the assembly */
5569 ass = ab->dynamic_assembly->assembly.image;
5570 module_count = ass->module_count;
5571 new_modules = g_new0 (MonoImage *, module_count + 1);
5574 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5575 new_modules [module_count] = &image->image;
5576 mono_image_addref (&image->image);
5578 g_free (ass->modules);
5579 ass->modules = new_modules;
5580 ass->module_count ++;
5585 * mono_assembly_get_object:
5586 * @domain: an app domain
5587 * @assembly: an assembly
5589 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5591 MonoReflectionAssembly*
5592 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5594 static MonoClass *System_Reflection_Assembly;
5595 MonoReflectionAssembly *res;
5597 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5598 if (!System_Reflection_Assembly)
5599 System_Reflection_Assembly = mono_class_from_name (
5600 mono_defaults.corlib, "System.Reflection", "Assembly");
5601 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5602 res->assembly = assembly;
5604 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5609 MonoReflectionModule*
5610 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5612 static MonoClass *System_Reflection_Module;
5613 MonoReflectionModule *res;
5616 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5617 if (!System_Reflection_Module)
5618 System_Reflection_Module = mono_class_from_name (
5619 mono_defaults.corlib, "System.Reflection", "Module");
5620 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5623 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5625 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5626 basename = g_path_get_basename (image->name);
5627 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5628 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5632 if (image->assembly->image == image) {
5633 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5637 if (image->assembly->image->modules) {
5638 for (i = 0; i < image->assembly->image->module_count; i++) {
5639 if (image->assembly->image->modules [i] == image)
5640 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5642 g_assert (res->token);
5646 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5649 MonoReflectionModule*
5650 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5652 static MonoClass *System_Reflection_Module;
5653 MonoReflectionModule *res;
5654 MonoTableInfo *table;
5655 guint32 cols [MONO_FILE_SIZE];
5657 guint32 i, name_idx;
5660 if (!System_Reflection_Module)
5661 System_Reflection_Module = mono_class_from_name (
5662 mono_defaults.corlib, "System.Reflection", "Module");
5663 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5665 table = &image->tables [MONO_TABLE_FILE];
5666 g_assert (table_index < table->rows);
5667 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5670 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5671 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5673 /* Check whenever the row has a corresponding row in the moduleref table */
5674 table = &image->tables [MONO_TABLE_MODULEREF];
5675 for (i = 0; i < table->rows; ++i) {
5676 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5677 val = mono_metadata_string_heap (image, name_idx);
5678 if (strcmp (val, name) == 0)
5679 res->image = image->modules [i];
5682 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5683 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5684 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5685 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5686 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5692 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5694 if ((t1->type != t2->type) ||
5695 (t1->byref != t2->byref))
5699 case MONO_TYPE_VOID:
5700 case MONO_TYPE_BOOLEAN:
5701 case MONO_TYPE_CHAR:
5712 case MONO_TYPE_STRING:
5715 case MONO_TYPE_OBJECT:
5716 case MONO_TYPE_TYPEDBYREF:
5718 case MONO_TYPE_VALUETYPE:
5719 case MONO_TYPE_CLASS:
5720 case MONO_TYPE_SZARRAY:
5721 return t1->data.klass == t2->data.klass;
5723 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5724 case MONO_TYPE_ARRAY:
5725 if (t1->data.array->rank != t2->data.array->rank)
5727 return t1->data.array->eklass == t2->data.array->eklass;
5728 case MONO_TYPE_GENERICINST: {
5730 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5731 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5732 if (i1->type_argc != i2->type_argc)
5734 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5735 &t2->data.generic_class->container_class->byval_arg))
5737 /* FIXME: we should probably just compare the instance pointers directly. */
5738 for (i = 0; i < i1->type_argc; ++i) {
5739 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5745 case MONO_TYPE_MVAR:
5746 return t1->data.generic_param == t2->data.generic_param;
5748 g_error ("implement type compare for %0x!", t1->type);
5756 mymono_metadata_type_hash (MonoType *t1)
5762 hash |= t1->byref << 6; /* do not collide with t1->type values */
5764 case MONO_TYPE_VALUETYPE:
5765 case MONO_TYPE_CLASS:
5766 case MONO_TYPE_SZARRAY:
5767 /* check if the distribution is good enough */
5768 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5770 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5771 case MONO_TYPE_GENERICINST: {
5773 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5774 hash += g_str_hash (t1->data.generic_class->container_class->name);
5776 for (i = 0; i < inst->type_argc; ++i) {
5777 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5786 static MonoReflectionGenericClass*
5787 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5789 static MonoClass *System_Reflection_MonoGenericClass;
5790 MonoReflectionGenericClass *res;
5791 MonoClass *klass, *gklass;
5793 if (!System_Reflection_MonoGenericClass) {
5794 System_Reflection_MonoGenericClass = mono_class_from_name (
5795 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5796 g_assert (System_Reflection_MonoGenericClass);
5799 klass = mono_class_from_mono_type (geninst);
5800 gklass = klass->generic_class->container_class;
5802 mono_class_init (klass);
5805 /* FIXME: allow unpinned later */
5806 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5808 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5811 res->type.type = geninst;
5812 g_assert (gklass->reflection_info);
5813 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
5814 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5820 verify_safe_for_managed_space (MonoType *type)
5822 switch (type->type) {
5824 case MONO_TYPE_ARRAY:
5825 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5827 return verify_safe_for_managed_space (type->data.type);
5828 case MONO_TYPE_SZARRAY:
5829 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5830 case MONO_TYPE_GENERICINST: {
5831 MonoGenericInst *inst = type->data.generic_class->inst;
5835 for (i = 0; i < inst->type_argc; ++i)
5836 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5842 case MONO_TYPE_MVAR:
5849 * mono_type_get_object:
5850 * @domain: an app domain
5853 * Return an System.MonoType object representing the type @type.
5856 mono_type_get_object (MonoDomain *domain, MonoType *type)
5858 MonoReflectionType *res;
5859 MonoClass *klass = mono_class_from_mono_type (type);
5861 /*we must avoid using @type as it might have come
5862 * from a mono_metadata_type_dup and the caller
5863 * expects that is can be freed.
5864 * Using the right type from
5866 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
5869 * If the vtable of the given class was already created, we can use
5870 * the MonoType from there and avoid all locking and hash table lookups.
5872 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
5873 * that the resulting object is diferent.
5875 if (type == &klass->byval_arg && !klass->image->dynamic) {
5876 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
5877 if (vtable && vtable->type)
5878 return vtable->type;
5881 mono_domain_lock (domain);
5882 if (!domain->type_hash)
5883 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5884 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5885 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5886 mono_domain_unlock (domain);
5889 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
5890 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
5891 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5892 mono_g_hash_table_insert (domain->type_hash, type, res);
5893 mono_domain_unlock (domain);
5897 if (!verify_safe_for_managed_space (type)) {
5898 mono_domain_unlock (domain);
5899 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5902 if (klass->reflection_info && !klass->wastypebuilder) {
5903 /* g_assert_not_reached (); */
5904 /* should this be considered an error condition? */
5906 mono_domain_unlock (domain);
5907 return klass->reflection_info;
5910 // FIXME: Get rid of this, do it in the icalls for Type
5911 mono_class_init (klass);
5913 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5915 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5918 mono_g_hash_table_insert (domain->type_hash, type, res);
5919 mono_domain_unlock (domain);
5924 * mono_method_get_object:
5925 * @domain: an app domain
5927 * @refclass: the reflected type (can be NULL)
5929 * Return an System.Reflection.MonoMethod object representing the method @method.
5931 MonoReflectionMethod*
5932 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5935 * We use the same C representation for methods and constructors, but the type
5936 * name in C# is different.
5938 static MonoClass *System_Reflection_MonoMethod = NULL;
5939 static MonoClass *System_Reflection_MonoCMethod = NULL;
5940 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5941 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5943 MonoReflectionMethod *ret;
5946 * Don't let static RGCTX invoke wrappers get into
5947 * MonoReflectionMethods.
5949 if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
5950 method = mono_marshal_method_from_wrapper (method);
5952 if (method->is_inflated) {
5953 MonoReflectionGenericMethod *gret;
5955 refclass = method->klass;
5956 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5957 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5958 if (!System_Reflection_MonoGenericCMethod)
5959 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5960 klass = System_Reflection_MonoGenericCMethod;
5962 if (!System_Reflection_MonoGenericMethod)
5963 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5964 klass = System_Reflection_MonoGenericMethod;
5966 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5967 gret->method.method = method;
5968 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5969 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5970 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5974 refclass = method->klass;
5976 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5977 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5978 if (!System_Reflection_MonoCMethod)
5979 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5980 klass = System_Reflection_MonoCMethod;
5983 if (!System_Reflection_MonoMethod)
5984 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5985 klass = System_Reflection_MonoMethod;
5987 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5988 ret->method = method;
5989 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5990 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5994 * mono_field_get_object:
5995 * @domain: an app domain
5999 * Return an System.Reflection.MonoField object representing the field @field
6002 MonoReflectionField*
6003 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6005 MonoReflectionField *res;
6006 static MonoClass *monofield_klass;
6008 CHECK_OBJECT (MonoReflectionField *, field, klass);
6009 if (!monofield_klass)
6010 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6011 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6014 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
6015 if (field->generic_info)
6016 res->attrs = field->generic_info->generic_type->attrs;
6018 res->attrs = field->type->attrs;
6019 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6020 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6024 * mono_property_get_object:
6025 * @domain: an app domain
6027 * @property: a property
6029 * Return an System.Reflection.MonoProperty object representing the property @property
6032 MonoReflectionProperty*
6033 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6035 MonoReflectionProperty *res;
6036 static MonoClass *monoproperty_klass;
6038 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6039 if (!monoproperty_klass)
6040 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6041 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6043 res->property = property;
6044 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6048 * mono_event_get_object:
6049 * @domain: an app domain
6053 * Return an System.Reflection.MonoEvent object representing the event @event
6056 MonoReflectionEvent*
6057 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6059 MonoReflectionEvent *res;
6060 static MonoClass *monoevent_klass;
6062 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6063 if (!monoevent_klass)
6064 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6065 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6068 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6072 * mono_get_reflection_missing_object:
6073 * @domain: Domain where the object lives
6075 * Returns the System.Reflection.Missing.Value singleton object
6076 * (of type System.Reflection.Missing).
6078 * Used as the value for ParameterInfo.DefaultValue when Optional
6082 mono_get_reflection_missing_object (MonoDomain *domain)
6085 static MonoClassField *missing_value_field = NULL;
6087 if (!missing_value_field) {
6088 MonoClass *missing_klass;
6089 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6090 mono_class_init (missing_klass);
6091 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6092 g_assert (missing_value_field);
6094 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6100 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6103 *dbnull = mono_get_dbnull_object (domain);
6108 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6110 if (!*reflection_missing)
6111 *reflection_missing = mono_get_reflection_missing_object (domain);
6112 return *reflection_missing;
6116 * mono_param_get_objects:
6117 * @domain: an app domain
6120 * Return an System.Reflection.ParameterInfo array object representing the parameters
6121 * in the method @method.
6124 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6126 static MonoClass *System_Reflection_ParameterInfo;
6127 static MonoClass *System_Reflection_ParameterInfo_array;
6128 MonoArray *res = NULL;
6129 MonoReflectionMethod *member = NULL;
6130 MonoReflectionParameter *param = NULL;
6131 char **names, **blobs = NULL;
6132 guint32 *types = NULL;
6133 MonoType *type = NULL;
6134 MonoObject *dbnull = NULL;
6135 MonoObject *missing = NULL;
6136 MonoMarshalSpec **mspecs;
6137 MonoMethodSignature *sig;
6138 MonoVTable *pinfo_vtable;
6141 if (!System_Reflection_ParameterInfo_array) {
6144 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6145 mono_memory_barrier ();
6146 System_Reflection_ParameterInfo = klass;
6148 klass = mono_array_class_get (klass, 1);
6149 mono_memory_barrier ();
6150 System_Reflection_ParameterInfo_array = klass;
6153 if (!mono_method_signature (method)->param_count)
6154 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6156 /* Note: the cache is based on the address of the signature into the method
6157 * since we already cache MethodInfos with the method as keys.
6159 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6161 sig = mono_method_signature (method);
6162 member = mono_method_get_object (domain, method, NULL);
6163 names = g_new (char *, sig->param_count);
6164 mono_method_get_param_names (method, (const char **) names);
6166 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6167 mono_method_get_marshal_info (method, mspecs);
6169 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6170 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6171 for (i = 0; i < sig->param_count; ++i) {
6172 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6173 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6174 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6175 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6176 param->PositionImpl = i;
6177 param->AttrsImpl = sig->params [i]->attrs;
6179 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6180 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6181 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6183 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6187 blobs = g_new0 (char *, sig->param_count);
6188 types = g_new0 (guint32, sig->param_count);
6189 get_default_param_value_blobs (method, blobs, types);
6192 /* Build MonoType for the type from the Constant Table */
6194 type = g_new0 (MonoType, 1);
6195 type->type = types [i];
6196 type->data.klass = NULL;
6197 if (types [i] == MONO_TYPE_CLASS)
6198 type->data.klass = mono_defaults.object_class;
6199 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6200 /* For enums, types [i] contains the base type */
6202 type->type = MONO_TYPE_VALUETYPE;
6203 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6205 type->data.klass = mono_class_from_mono_type (type);
6207 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6209 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6210 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6211 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6212 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6214 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6220 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6222 mono_array_setref (res, i, param);
6229 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6231 mono_metadata_free_marshal_spec (mspecs [i]);
6234 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6238 * mono_method_body_get_object:
6239 * @domain: an app domain
6242 * Return an System.Reflection.MethodBody object representing the method @method.
6244 MonoReflectionMethodBody*
6245 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6247 static MonoClass *System_Reflection_MethodBody = NULL;
6248 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6249 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6250 MonoReflectionMethodBody *ret;
6251 MonoMethodNormal *mn;
6252 MonoMethodHeader *header;
6253 guint32 method_rva, local_var_sig_token;
6255 unsigned char format, flags;
6258 if (!System_Reflection_MethodBody)
6259 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6260 if (!System_Reflection_LocalVariableInfo)
6261 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6262 if (!System_Reflection_ExceptionHandlingClause)
6263 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6265 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6267 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6268 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6269 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6270 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6272 mn = (MonoMethodNormal *)method;
6273 header = mono_method_get_header (method);
6275 /* Obtain local vars signature token */
6276 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6277 ptr = mono_image_rva_map (method->klass->image, method_rva);
6278 flags = *(const unsigned char *) ptr;
6279 format = flags & METHOD_HEADER_FORMAT_MASK;
6281 case METHOD_HEADER_TINY_FORMAT:
6282 case METHOD_HEADER_TINY_FORMAT1:
6283 local_var_sig_token = 0;
6285 case METHOD_HEADER_FAT_FORMAT:
6289 local_var_sig_token = read32 (ptr);
6292 g_assert_not_reached ();
6295 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6297 ret->init_locals = header->init_locals;
6298 ret->max_stack = header->max_stack;
6299 ret->local_var_sig_token = local_var_sig_token;
6300 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6301 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6304 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6305 for (i = 0; i < header->num_locals; ++i) {
6306 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6307 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6308 info->is_pinned = header->locals [i]->pinned;
6309 info->local_index = i;
6310 mono_array_setref (ret->locals, i, info);
6314 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6315 for (i = 0; i < header->num_clauses; ++i) {
6316 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6317 MonoExceptionClause *clause = &header->clauses [i];
6319 info->flags = clause->flags;
6320 info->try_offset = clause->try_offset;
6321 info->try_length = clause->try_len;
6322 info->handler_offset = clause->handler_offset;
6323 info->handler_length = clause->handler_len;
6324 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6325 info->filter_offset = clause->data.filter_offset;
6326 else if (clause->data.catch_class)
6327 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6329 mono_array_setref (ret->clauses, i, info);
6332 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6337 * mono_get_dbnull_object:
6338 * @domain: Domain where the object lives
6340 * Returns the System.DBNull.Value singleton object
6342 * Used as the value for ParameterInfo.DefaultValue
6345 mono_get_dbnull_object (MonoDomain *domain)
6348 static MonoClassField *dbnull_value_field = NULL;
6350 if (!dbnull_value_field) {
6351 MonoClass *dbnull_klass;
6352 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6353 mono_class_init (dbnull_klass);
6354 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6355 g_assert (dbnull_value_field);
6357 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6363 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6365 guint32 param_index, i, lastp, crow = 0;
6366 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6369 MonoClass *klass = method->klass;
6370 MonoImage *image = klass->image;
6371 MonoMethodSignature *methodsig = mono_method_signature (method);
6373 MonoTableInfo *constt;
6374 MonoTableInfo *methodt;
6375 MonoTableInfo *paramt;
6377 if (!methodsig->param_count)
6380 mono_class_init (klass);
6382 if (klass->image->dynamic) {
6383 MonoReflectionMethodAux *aux;
6384 if (method->is_inflated)
6385 method = ((MonoMethodInflated*)method)->declaring;
6386 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6387 if (aux && aux->param_defaults) {
6388 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6389 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6394 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6395 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6396 constt = &image->tables [MONO_TABLE_CONSTANT];
6398 idx = mono_method_get_index (method) - 1;
6399 g_assert (idx != -1);
6401 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6402 if (idx + 1 < methodt->rows)
6403 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6405 lastp = paramt->rows + 1;
6407 for (i = param_index; i < lastp; ++i) {
6410 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6411 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6413 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6416 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6421 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6422 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6423 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6430 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6435 MonoType *basetype = type;
6440 klass = mono_class_from_mono_type (type);
6441 if (klass->valuetype) {
6442 object = mono_object_new (domain, klass);
6443 retval = ((gchar *) object + sizeof (MonoObject));
6444 if (klass->enumtype)
6445 basetype = klass->enum_basetype;
6450 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6457 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6461 memset (assembly, 0, sizeof (MonoAssemblyName));
6463 assembly->culture = "";
6464 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6466 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6469 while (g_ascii_isspace (*p) || *p == ',') {
6478 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6480 assembly->major = strtoul (p, &s, 10);
6481 if (s == p || *s != '.')
6484 assembly->minor = strtoul (p, &s, 10);
6485 if (s == p || *s != '.')
6488 assembly->build = strtoul (p, &s, 10);
6489 if (s == p || *s != '.')
6492 assembly->revision = strtoul (p, &s, 10);
6496 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6498 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6499 assembly->culture = "";
6502 assembly->culture = p;
6503 while (*p && *p != ',') {
6507 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6509 if (strncmp (p, "null", 4) == 0) {
6514 while (*p && *p != ',') {
6517 len = (p - start + 1);
6518 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6519 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6520 g_strlcpy ((char*)assembly->public_key_token, start, len);
6523 while (*p && *p != ',')
6527 while (g_ascii_isspace (*p) || *p == ',') {
6541 * mono_reflection_parse_type:
6544 * Parse a type name as accepted by the GetType () method and output the info
6545 * extracted in the info structure.
6546 * the name param will be mangled, so, make a copy before passing it to this function.
6547 * The fields in info will be valid until the memory pointed to by name is valid.
6549 * See also mono_type_get_name () below.
6551 * Returns: 0 on parse error.
6554 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6555 MonoTypeNameParse *info)
6557 char *start, *p, *w, *temp, *last_point, *startn;
6558 int in_modifiers = 0;
6559 int isbyref = 0, rank, arity = 0, i;
6561 start = p = w = name;
6563 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6564 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6565 info->name = info->name_space = NULL;
6566 info->nested = NULL;
6567 info->modifiers = NULL;
6568 info->type_arguments = NULL;
6570 /* last_point separates the namespace from the name */
6576 *p = 0; /* NULL terminate the name */
6578 info->nested = g_list_append (info->nested, startn);
6579 /* we have parsed the nesting namespace + name */
6583 info->name_space = start;
6585 info->name = last_point + 1;
6587 info->name_space = (char *)"";
6606 i = strtol (p, &temp, 10);
6623 info->name_space = start;
6625 info->name = last_point + 1;
6627 info->name_space = (char *)"";
6634 if (isbyref) /* only one level allowed by the spec */
6637 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6641 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6647 info->type_arguments = g_ptr_array_new ();
6648 for (i = 0; i < arity; i++) {
6649 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6650 gboolean fqname = FALSE;
6652 g_ptr_array_add (info->type_arguments, subinfo);
6659 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6670 while (*p && (*p != ']'))
6678 if (g_ascii_isspace (*aname)) {
6685 !assembly_name_to_aname (&subinfo->assembly, aname))
6689 if (i + 1 < arity) {
6709 else if (*p == '*') /* '*' means unknown lower bound */
6710 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6717 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6728 if (g_ascii_isspace (*p)) {
6735 return 0; /* missing assembly name */
6736 if (!assembly_name_to_aname (&info->assembly, p))
6742 if (info->assembly.name)
6745 // *w = 0; /* terminate class name */
6747 if (!info->name || !*info->name)
6751 /* add other consistency checks */
6756 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6758 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6762 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6764 gboolean type_resolve = FALSE;
6766 MonoImage *rootimage = image;
6768 if (info->assembly.name) {
6769 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6771 /* then we must load the assembly ourselve - see #60439 */
6772 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6776 image = assembly->image;
6777 } else if (!image) {
6778 image = mono_defaults.corlib;
6781 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6782 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6783 image = mono_defaults.corlib;
6784 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6791 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6796 gboolean bounded = FALSE;
6799 image = mono_defaults.corlib;
6802 klass = mono_class_from_name_case (image, info->name_space, info->name);
6804 klass = mono_class_from_name (image, info->name_space, info->name);
6807 for (mod = info->nested; mod; mod = mod->next) {
6810 mono_class_init (klass);
6811 nested = klass->nested_classes;
6814 klass = nested->data;
6816 if (g_strcasecmp (klass->name, mod->data) == 0)
6819 if (strcmp (klass->name, mod->data) == 0)
6823 nested = nested->next;
6830 mono_class_init (klass);
6832 if (info->type_arguments) {
6833 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6834 MonoReflectionType *the_type;
6838 for (i = 0; i < info->type_arguments->len; i++) {
6839 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6841 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
6842 if (!type_args [i]) {
6848 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6850 instance = mono_reflection_bind_generic_parameters (
6851 the_type, info->type_arguments->len, type_args);
6857 klass = mono_class_from_mono_type (instance);
6860 for (mod = info->modifiers; mod; mod = mod->next) {
6861 modval = GPOINTER_TO_UINT (mod->data);
6862 if (!modval) { /* byref: must be last modifier */
6863 return &klass->this_arg;
6864 } else if (modval == -1) {
6865 klass = mono_ptr_class_get (&klass->byval_arg);
6866 } else if (modval == -2) {
6868 } else { /* array rank */
6869 klass = mono_bounded_array_class_get (klass, modval, bounded);
6871 mono_class_init (klass);
6874 return &klass->byval_arg;
6878 * mono_reflection_get_type:
6879 * @image: a metadata context
6880 * @info: type description structure
6881 * @ignorecase: flag for case-insensitive string compares
6882 * @type_resolve: whenever type resolve was already tried
6884 * Build a MonoType from the type description in @info.
6889 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
6890 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
6894 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
6896 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
6900 g_assert (assembly->dynamic);
6902 /* Enumerate all modules */
6905 if (abuilder->modules) {
6906 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6907 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6908 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
6914 if (!type && abuilder->loaded_modules) {
6915 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6916 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6917 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
6927 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6930 MonoReflectionAssembly *assembly;
6934 if (image && image->dynamic)
6935 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
6937 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
6940 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6947 *type_resolve = TRUE;
6950 /* Reconstruct the type name */
6951 fullName = g_string_new ("");
6952 if (info->name_space && (info->name_space [0] != '\0'))
6953 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6955 g_string_printf (fullName, info->name);
6956 for (mod = info->nested; mod; mod = mod->next)
6957 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6959 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6961 if (assembly->assembly->dynamic)
6962 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
6964 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
6967 g_string_free (fullName, TRUE);
6972 mono_reflection_free_type_info (MonoTypeNameParse *info)
6974 g_list_free (info->modifiers);
6975 g_list_free (info->nested);
6977 if (info->type_arguments) {
6980 for (i = 0; i < info->type_arguments->len; i++) {
6981 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6983 mono_reflection_free_type_info (subinfo);
6984 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
6988 g_ptr_array_free (info->type_arguments, TRUE);
6993 * mono_reflection_type_from_name:
6995 * @image: a metadata context (can be NULL).
6997 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6998 * it defaults to get the type from @image or, if @image is NULL or loading
6999 * from it fails, uses corlib.
7003 mono_reflection_type_from_name (char *name, MonoImage *image)
7005 MonoType *type = NULL;
7006 MonoTypeNameParse info;
7009 /* Make a copy since parse_type modifies its argument */
7010 tmp = g_strdup (name);
7012 /*g_print ("requested type %s\n", str);*/
7013 if (mono_reflection_parse_type (tmp, &info)) {
7014 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7018 mono_reflection_free_type_info (&info);
7023 * mono_reflection_get_token:
7025 * Return the metadata token of OBJ which should be an object
7026 * representing a metadata element.
7029 mono_reflection_get_token (MonoObject *obj)
7034 klass = obj->vtable->klass;
7036 if (strcmp (klass->name, "MethodBuilder") == 0) {
7037 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7039 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7040 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7041 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7043 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7044 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7045 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7047 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7048 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7049 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7050 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7051 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7052 } else if (strcmp (klass->name, "MonoType") == 0) {
7053 MonoReflectionType *tb = (MonoReflectionType *)obj;
7054 token = mono_class_from_mono_type (tb->type)->type_token;
7055 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7056 strcmp (klass->name, "MonoMethod") == 0 ||
7057 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7058 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7059 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7060 if (m->method->is_inflated) {
7061 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7062 return inflated->declaring->token;
7064 token = m->method->token;
7066 } else if (strcmp (klass->name, "MonoField") == 0) {
7067 MonoReflectionField *f = (MonoReflectionField*)obj;
7069 if (f->field->generic_info && f->field->generic_info->reflection_info)
7070 return mono_reflection_get_token (f->field->generic_info->reflection_info);
7072 token = mono_class_get_field_token (f->field);
7073 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7074 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7076 token = mono_class_get_property_token (p->property);
7077 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7078 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7080 token = mono_class_get_event_token (p->event);
7081 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7082 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7084 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7085 } else if (strcmp (klass->name, "Module") == 0) {
7086 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7089 } else if (strcmp (klass->name, "Assembly") == 0) {
7090 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7092 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7093 MonoException *ex = mono_get_exception_not_implemented (msg);
7095 mono_raise_exception (ex);
7102 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7104 int slen, type = t->type;
7105 MonoClass *tklass = t->data.klass;
7111 case MONO_TYPE_BOOLEAN: {
7112 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7117 case MONO_TYPE_CHAR:
7119 case MONO_TYPE_I2: {
7120 guint16 *val = g_malloc (sizeof (guint16));
7125 #if SIZEOF_VOID_P == 4
7131 case MONO_TYPE_I4: {
7132 guint32 *val = g_malloc (sizeof (guint32));
7137 #if SIZEOF_VOID_P == 8
7138 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7142 case MONO_TYPE_I8: {
7143 guint64 *val = g_malloc (sizeof (guint64));
7148 case MONO_TYPE_R8: {
7149 double *val = g_malloc (sizeof (double));
7154 case MONO_TYPE_VALUETYPE:
7155 if (t->data.klass->enumtype) {
7156 type = t->data.klass->enum_basetype->type;
7159 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7162 case MONO_TYPE_STRING:
7163 if (*p == (char)0xFF) {
7167 slen = mono_metadata_decode_value (p, &p);
7169 return mono_string_new_len (mono_domain_get (), p, slen);
7170 case MONO_TYPE_CLASS: {
7173 if (*p == (char)0xFF) {
7178 slen = mono_metadata_decode_value (p, &p);
7179 n = g_memdup (p, slen + 1);
7181 t = mono_reflection_type_from_name (n, image);
7183 g_warning ("Cannot load type '%s'", n);
7187 return mono_type_get_object (mono_domain_get (), t);
7191 case MONO_TYPE_OBJECT: {
7194 MonoClass *subc = NULL;
7199 } else if (subt == 0x0E) {
7200 type = MONO_TYPE_STRING;
7202 } else if (subt == 0x1D) {
7203 MonoType simple_type = {{0}};
7208 /* See Partition II, Appendix B3 */
7209 etype = MONO_TYPE_OBJECT;
7210 type = MONO_TYPE_SZARRAY;
7211 simple_type.type = etype;
7212 tklass = mono_class_from_mono_type (&simple_type);
7214 } else if (subt == 0x55) {
7217 slen = mono_metadata_decode_value (p, &p);
7218 n = g_memdup (p, slen + 1);
7220 t = mono_reflection_type_from_name (n, image);
7222 g_error ("Cannot load type '%s'", n);
7225 subc = mono_class_from_mono_type (t);
7226 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7227 MonoType simple_type = {{0}};
7228 simple_type.type = subt;
7229 subc = mono_class_from_mono_type (&simple_type);
7231 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7233 val = load_cattr_value (image, &subc->byval_arg, p, end);
7234 obj = mono_object_new (mono_domain_get (), subc);
7235 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7239 case MONO_TYPE_SZARRAY: {
7241 guint32 i, alen, basetype;
7244 if (alen == 0xffffffff) {
7248 arr = mono_array_new (mono_domain_get(), tklass, alen);
7249 basetype = tklass->byval_arg.type;
7250 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7251 basetype = tklass->enum_basetype->type;
7256 case MONO_TYPE_BOOLEAN:
7257 for (i = 0; i < alen; i++) {
7258 MonoBoolean val = *p++;
7259 mono_array_set (arr, MonoBoolean, i, val);
7262 case MONO_TYPE_CHAR:
7265 for (i = 0; i < alen; i++) {
7266 guint16 val = read16 (p);
7267 mono_array_set (arr, guint16, i, val);
7274 for (i = 0; i < alen; i++) {
7275 guint32 val = read32 (p);
7276 mono_array_set (arr, guint32, i, val);
7281 for (i = 0; i < alen; i++) {
7284 mono_array_set (arr, double, i, val);
7290 for (i = 0; i < alen; i++) {
7291 guint64 val = read64 (p);
7292 mono_array_set (arr, guint64, i, val);
7296 case MONO_TYPE_CLASS:
7297 case MONO_TYPE_OBJECT:
7298 case MONO_TYPE_STRING:
7299 for (i = 0; i < alen; i++) {
7300 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7301 mono_array_setref (arr, i, item);
7305 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7311 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7317 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7319 static MonoClass *klass;
7320 static MonoMethod *ctor;
7322 void *params [2], *unboxed;
7325 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7327 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7329 params [0] = mono_type_get_object (mono_domain_get (), t);
7331 retval = mono_object_new (mono_domain_get (), klass);
7332 unboxed = mono_object_unbox (retval);
7333 mono_runtime_invoke (ctor, unboxed, params, NULL);
7339 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7341 static MonoClass *klass;
7342 static MonoMethod *ctor;
7344 void *unboxed, *params [2];
7347 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7349 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7352 params [1] = typedarg;
7353 retval = mono_object_new (mono_domain_get (), klass);
7354 unboxed = mono_object_unbox (retval);
7355 mono_runtime_invoke (ctor, unboxed, params, NULL);
7361 type_is_reference (MonoType *type)
7363 switch (type->type) {
7364 case MONO_TYPE_BOOLEAN:
7365 case MONO_TYPE_CHAR:
7378 case MONO_TYPE_VALUETYPE:
7386 free_param_data (MonoMethodSignature *sig, void **params) {
7388 for (i = 0; i < sig->param_count; ++i) {
7389 if (!type_is_reference (sig->params [i]))
7390 g_free (params [i]);
7395 * Find the field index in the metadata FieldDef table.
7398 find_field_index (MonoClass *klass, MonoClassField *field) {
7401 for (i = 0; i < klass->field.count; ++i) {
7402 if (field == &klass->fields [i])
7403 return klass->field.first + 1 + i;
7409 * Find the property index in the metadata Property table.
7412 find_property_index (MonoClass *klass, MonoProperty *property) {
7415 for (i = 0; i < klass->property.count; ++i) {
7416 if (property == &klass->properties [i])
7417 return klass->property.first + 1 + i;
7423 * Find the event index in the metadata Event table.
7426 find_event_index (MonoClass *klass, MonoEvent *event) {
7429 for (i = 0; i < klass->event.count; ++i) {
7430 if (event == &klass->events [i])
7431 return klass->event.first + 1 + i;
7437 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7439 const char *p = (const char*)data;
7441 guint32 i, j, num_named;
7445 mono_class_init (method->klass);
7448 attr = mono_object_new (mono_domain_get (), method->klass);
7449 mono_runtime_invoke (method, attr, NULL, NULL);
7453 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7456 /*g_print ("got attr %s\n", method->klass->name);*/
7458 /* Allocate using alloca so it gets GC tracking */
7459 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7463 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7464 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7468 attr = mono_object_new (mono_domain_get (), method->klass);
7469 mono_runtime_invoke (method, attr, params, NULL);
7470 free_param_data (method->signature, params);
7471 num_named = read16 (named);
7473 for (j = 0; j < num_named; j++) {
7475 char *name, named_type, data_type;
7476 named_type = *named++;
7477 data_type = *named++; /* type of data */
7478 if (data_type == MONO_TYPE_SZARRAY)
7479 data_type = *named++;
7480 if (data_type == MONO_TYPE_ENUM) {
7483 type_len = mono_metadata_decode_blob_size (named, &named);
7484 type_name = g_malloc (type_len + 1);
7485 memcpy (type_name, named, type_len);
7486 type_name [type_len] = 0;
7488 /* FIXME: lookup the type and check type consistency */
7491 name_len = mono_metadata_decode_blob_size (named, &named);
7492 name = g_malloc (name_len + 1);
7493 memcpy (name, named, name_len);
7494 name [name_len] = 0;
7496 if (named_type == 0x53) {
7497 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7498 void *val = load_cattr_value (image, field->type, named, &named);
7499 mono_field_set_value (attr, field, val);
7500 if (!type_is_reference (field->type))
7502 } else if (named_type == 0x54) {
7505 MonoType *prop_type;
7507 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7508 /* can we have more that 1 arg in a custom attr named property? */
7509 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7510 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7511 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7512 mono_property_set_value (prop, attr, pparams, NULL);
7513 if (!type_is_reference (prop_type))
7514 g_free (pparams [0]);
7523 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7525 MonoArray *typedargs, *namedargs;
7526 MonoClass *attrklass;
7527 static MonoMethod *ctor;
7530 const char *p = (const char*)data;
7532 guint32 i, j, num_named;
7535 mono_class_init (method->klass);
7538 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7540 domain = mono_domain_get ();
7542 /* This is for Attributes with no parameters */
7543 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7544 params [0] = mono_method_get_object (domain, method, NULL);
7545 params [1] = params [2] = NULL;
7546 mono_runtime_invoke (method, attr, params, NULL);
7550 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7553 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7557 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7558 MonoObject *obj, *typedarg;
7561 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7562 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7563 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7564 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7565 mono_array_setref (typedargs, i, typedarg);
7567 if (!type_is_reference (mono_method_signature (method)->params [i]))
7572 num_named = read16 (named);
7573 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7575 attrklass = method->klass;
7576 for (j = 0; j < num_named; j++) {
7578 char *name, named_type, data_type;
7579 named_type = *named++;
7580 data_type = *named++; /* type of data */
7581 if (data_type == MONO_TYPE_SZARRAY)
7582 data_type = *named++;
7583 if (data_type == MONO_TYPE_ENUM) {
7586 type_len = mono_metadata_decode_blob_size (named, &named);
7587 type_name = g_malloc (type_len + 1);
7588 memcpy (type_name, named, type_len);
7589 type_name [type_len] = 0;
7591 /* FIXME: lookup the type and check type consistency */
7594 name_len = mono_metadata_decode_blob_size (named, &named);
7595 name = g_malloc (name_len + 1);
7596 memcpy (name, named, name_len);
7597 name [name_len] = 0;
7599 if (named_type == 0x53) {
7600 MonoObject *obj, *typedarg, *namedarg;
7601 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7602 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7604 minfo = mono_field_get_object (domain, NULL, field);
7605 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7606 typedarg = create_cattr_typed_arg (field->type, obj);
7607 namedarg = create_cattr_named_arg (minfo, typedarg);
7608 mono_array_setref (namedargs, j, namedarg);
7609 if (!type_is_reference (field->type))
7611 } else if (named_type == 0x54) {
7612 MonoObject *obj, *typedarg, *namedarg;
7613 MonoType *prop_type;
7615 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7617 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7618 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7619 minfo = mono_property_get_object (domain, NULL, prop);
7620 val = load_cattr_value (image, prop_type, named, &named);
7621 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7622 typedarg = create_cattr_typed_arg (prop_type, obj);
7623 namedarg = create_cattr_named_arg (minfo, typedarg);
7624 mono_array_setref (namedargs, j, namedarg);
7625 if (!type_is_reference (prop_type))
7630 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7631 params [0] = mono_method_get_object (domain, method, NULL);
7632 params [1] = typedargs;
7633 params [2] = namedargs;
7634 mono_runtime_invoke (ctor, attr, params, NULL);
7639 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7645 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7646 for (i = 0; i < cinfo->num_attrs; ++i) {
7647 if (!cinfo->attrs [i].ctor)
7648 /* The cattr type is not finished yet */
7649 /* We should include the type name but cinfo doesn't contain it */
7650 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7651 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7652 mono_array_setref (result, i, attr);
7658 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7665 for (i = 0; i < cinfo->num_attrs; ++i) {
7666 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7670 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7672 for (i = 0; i < cinfo->num_attrs; ++i) {
7673 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7674 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7675 mono_array_setref (result, n, attr);
7683 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7689 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7690 for (i = 0; i < cinfo->num_attrs; ++i) {
7691 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7692 mono_array_setref (result, i, attr);
7698 * mono_custom_attrs_from_index:
7700 * Returns: NULL if no attributes are found or if a loading error occurs.
7703 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7705 guint32 mtoken, i, len;
7706 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7708 MonoCustomAttrInfo *ainfo;
7709 GList *tmp, *list = NULL;
7712 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7714 i = mono_metadata_custom_attrs_from_index (image, idx);
7718 while (i < ca->rows) {
7719 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7721 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7724 len = g_list_length (list);
7727 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7728 ainfo->num_attrs = len;
7729 ainfo->image = image;
7730 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7731 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7732 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7733 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7734 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7735 mtoken |= MONO_TOKEN_METHOD_DEF;
7737 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7738 mtoken |= MONO_TOKEN_MEMBER_REF;
7741 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7744 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7745 if (!ainfo->attrs [i].ctor) {
7746 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7751 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7752 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7753 ainfo->attrs [i].data = (guchar*)data;
7761 mono_custom_attrs_from_method (MonoMethod *method)
7766 * An instantiated method has the same cattrs as the generic method definition.
7768 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7769 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7771 if (method->is_inflated)
7772 method = ((MonoMethodInflated *) method)->declaring;
7774 if (method->dynamic || method->klass->image->dynamic)
7775 return lookup_custom_attr (method->klass->image, method);
7777 idx = mono_method_get_index (method);
7778 idx <<= MONO_CUSTOM_ATTR_BITS;
7779 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7780 return mono_custom_attrs_from_index (method->klass->image, idx);
7784 mono_custom_attrs_from_class (MonoClass *klass)
7788 if (klass->generic_class)
7789 klass = klass->generic_class->container_class;
7791 if (klass->image->dynamic)
7792 return lookup_custom_attr (klass->image, klass);
7794 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
7795 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
7796 idx <<= MONO_CUSTOM_ATTR_BITS;
7797 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
7799 idx = mono_metadata_token_index (klass->type_token);
7800 idx <<= MONO_CUSTOM_ATTR_BITS;
7801 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7803 return mono_custom_attrs_from_index (klass->image, idx);
7807 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7811 if (assembly->image->dynamic)
7812 return lookup_custom_attr (assembly->image, assembly);
7813 idx = 1; /* there is only one assembly */
7814 idx <<= MONO_CUSTOM_ATTR_BITS;
7815 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7816 return mono_custom_attrs_from_index (assembly->image, idx);
7819 static MonoCustomAttrInfo*
7820 mono_custom_attrs_from_module (MonoImage *image)
7825 return lookup_custom_attr (image, image);
7826 idx = 1; /* there is only one module */
7827 idx <<= MONO_CUSTOM_ATTR_BITS;
7828 idx |= MONO_CUSTOM_ATTR_MODULE;
7829 return mono_custom_attrs_from_index (image, idx);
7833 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7837 if (klass->image->dynamic) {
7838 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
7839 return lookup_custom_attr (klass->image, property);
7841 idx = find_property_index (klass, property);
7842 idx <<= MONO_CUSTOM_ATTR_BITS;
7843 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7844 return mono_custom_attrs_from_index (klass->image, idx);
7848 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7852 if (klass->image->dynamic) {
7853 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
7854 return lookup_custom_attr (klass->image, event);
7856 idx = find_event_index (klass, event);
7857 idx <<= MONO_CUSTOM_ATTR_BITS;
7858 idx |= MONO_CUSTOM_ATTR_EVENT;
7859 return mono_custom_attrs_from_index (klass->image, idx);
7863 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7866 if (klass->image->dynamic) {
7867 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
7868 return lookup_custom_attr (klass->image, field);
7870 idx = find_field_index (klass, field);
7871 idx <<= MONO_CUSTOM_ATTR_BITS;
7872 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7873 return mono_custom_attrs_from_index (klass->image, idx);
7877 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7880 guint32 i, idx, method_index;
7881 guint32 param_list, param_last, param_pos, found;
7883 MonoReflectionMethodAux *aux;
7886 * An instantiated method has the same cattrs as the generic method definition.
7888 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7889 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7891 if (method->is_inflated)
7892 method = ((MonoMethodInflated *) method)->declaring;
7894 if (method->klass->image->dynamic) {
7895 MonoCustomAttrInfo *res, *ainfo;
7898 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7899 if (!aux || !aux->param_cattr)
7902 /* Need to copy since it will be freed later */
7903 ainfo = aux->param_cattr [param];
7904 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7905 res = g_malloc0 (size);
7906 memcpy (res, ainfo, size);
7910 image = method->klass->image;
7911 method_index = mono_method_get_index (method);
7912 ca = &image->tables [MONO_TABLE_METHOD];
7914 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7915 if (method_index == ca->rows) {
7916 ca = &image->tables [MONO_TABLE_PARAM];
7917 param_last = ca->rows + 1;
7919 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7920 ca = &image->tables [MONO_TABLE_PARAM];
7923 for (i = param_list; i < param_last; ++i) {
7924 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7925 if (param_pos == param) {
7933 idx <<= MONO_CUSTOM_ATTR_BITS;
7934 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7935 return mono_custom_attrs_from_index (image, idx);
7939 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7943 for (i = 0; i < ainfo->num_attrs; ++i) {
7944 klass = ainfo->attrs [i].ctor->klass;
7945 if (mono_class_has_parent (klass, attr_klass))
7952 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7959 for (i = 0; i < ainfo->num_attrs; ++i) {
7960 klass = ainfo->attrs [i].ctor->klass;
7961 if (mono_class_has_parent (klass, attr_klass)) {
7966 if (attr_index == -1)
7969 attrs = mono_custom_attrs_construct (ainfo);
7971 return mono_array_get (attrs, MonoObject*, attr_index);
7977 * mono_reflection_get_custom_attrs_info:
7978 * @obj: a reflection object handle
7980 * Return the custom attribute info for attributes defined for the
7981 * reflection handle @obj. The objects.
7984 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7987 MonoCustomAttrInfo *cinfo = NULL;
7989 klass = obj->vtable->klass;
7990 if (klass == mono_defaults.monotype_class) {
7991 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7992 klass = mono_class_from_mono_type (rtype->type);
7993 cinfo = mono_custom_attrs_from_class (klass);
7994 } else if (strcmp ("Assembly", klass->name) == 0) {
7995 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7996 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7997 } else if (strcmp ("Module", klass->name) == 0) {
7998 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7999 cinfo = mono_custom_attrs_from_module (module->image);
8000 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8001 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8002 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8003 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8004 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
8005 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8006 } else if (strcmp ("MonoField", klass->name) == 0) {
8007 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8008 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8009 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8010 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8011 cinfo = mono_custom_attrs_from_method (rmethod->method);
8012 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8013 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8014 cinfo = mono_custom_attrs_from_method (rmethod->method);
8015 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8016 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8017 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8018 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8019 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8020 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8021 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8022 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8023 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8024 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8025 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8026 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8027 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8028 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8029 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8030 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8031 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8032 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8033 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8034 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8035 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8036 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8037 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8038 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8039 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8040 } else { /* handle other types here... */
8041 g_error ("get custom attrs not yet supported for %s", klass->name);
8048 * mono_reflection_get_custom_attrs_by_type:
8049 * @obj: a reflection object handle
8051 * Return an array with all the custom attributes defined of the
8052 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8053 * of that type are returned. The objects are fully build. Return NULL if a loading error
8057 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8060 MonoCustomAttrInfo *cinfo;
8062 cinfo = mono_reflection_get_custom_attrs_info (obj);
8065 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8067 result = mono_custom_attrs_construct (cinfo);
8069 mono_custom_attrs_free (cinfo);
8071 if (mono_loader_get_last_error ())
8073 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8080 * mono_reflection_get_custom_attrs:
8081 * @obj: a reflection object handle
8083 * Return an array with all the custom attributes defined of the
8084 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8088 mono_reflection_get_custom_attrs (MonoObject *obj)
8090 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8094 * mono_reflection_get_custom_attrs_data:
8095 * @obj: a reflection obj handle
8097 * Returns an array of System.Reflection.CustomAttributeData,
8098 * which include information about attributes reflected on
8099 * types loaded using the Reflection Only methods
8102 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8105 MonoCustomAttrInfo *cinfo;
8107 cinfo = mono_reflection_get_custom_attrs_info (obj);
8109 result = mono_custom_attrs_data_construct (cinfo);
8111 mono_custom_attrs_free (cinfo);
8113 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8118 static MonoReflectionType*
8119 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8121 MonoMethod *method_get_underlying_system_type;
8123 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8124 mono_class_get_method_from_name (mono_object_class (t),
8125 "get_UnderlyingSystemType",
8127 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8131 mono_reflection_type_get_handle (MonoReflectionType* t)
8136 t = mono_reflection_type_get_underlying_system_type (t);
8144 * LOCKING: Assumes the loader lock is held.
8146 static MonoMethodSignature*
8147 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
8148 MonoMethodSignature *sig;
8151 count = parameters? mono_array_length (parameters): 0;
8153 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8154 sig->param_count = count;
8155 sig->sentinelpos = -1; /* FIXME */
8156 for (i = 0; i < count; ++i) {
8157 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8158 sig->params [i] = mono_reflection_type_get_handle (pt);
8164 * LOCKING: Assumes the loader lock is held.
8166 static MonoMethodSignature*
8167 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
8168 MonoMethodSignature *sig;
8170 sig = parameters_to_signature (mp, ctor->parameters);
8171 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8172 sig->ret = &mono_defaults.void_class->byval_arg;
8177 * LOCKING: Assumes the loader lock is held.
8179 static MonoMethodSignature*
8180 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
8181 MonoMethodSignature *sig;
8183 sig = parameters_to_signature (mp, method->parameters);
8184 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8185 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8186 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8190 static MonoMethodSignature*
8191 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8192 MonoMethodSignature *sig;
8194 sig = parameters_to_signature (NULL, method->parameters);
8195 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8196 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8197 sig->generic_param_count = 0;
8202 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8204 MonoClass *klass = mono_object_class (prop);
8205 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8206 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8207 *name = mono_string_to_utf8 (pb->name);
8208 *type = pb->type->type;
8210 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8211 *name = g_strdup (p->property->name);
8212 if (p->property->get)
8213 *type = mono_method_signature (p->property->get)->ret;
8215 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8220 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8222 MonoClass *klass = mono_object_class (field);
8223 if (strcmp (klass->name, "FieldBuilder") == 0) {
8224 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8225 *name = mono_string_to_utf8 (fb->name);
8226 *type = fb->type->type;
8228 MonoReflectionField *f = (MonoReflectionField *)field;
8229 *name = g_strdup (f->field->name);
8230 *type = f->field->type;
8235 * Encode a value in a custom attribute stream of bytes.
8236 * The value to encode is either supplied as an object in argument val
8237 * (valuetypes are boxed), or as a pointer to the data in the
8239 * @type represents the type of the value
8240 * @buffer is the start of the buffer
8241 * @p the current position in the buffer
8242 * @buflen contains the size of the buffer and is used to return the new buffer size
8243 * if this needs to be realloced.
8244 * @retbuffer and @retp return the start and the position of the buffer
8247 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8249 MonoTypeEnum simple_type;
8251 if ((p-buffer) + 10 >= *buflen) {
8254 newbuf = g_realloc (buffer, *buflen);
8255 p = newbuf + (p-buffer);
8259 argval = ((char*)arg + sizeof (MonoObject));
8260 simple_type = type->type;
8262 switch (simple_type) {
8263 case MONO_TYPE_BOOLEAN:
8268 case MONO_TYPE_CHAR:
8271 swap_with_size (p, argval, 2, 1);
8277 swap_with_size (p, argval, 4, 1);
8281 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8291 swap_with_size (p, argval, 8, 1);
8297 swap_with_size (p, argval, 8, 1);
8300 case MONO_TYPE_VALUETYPE:
8301 if (type->data.klass->enumtype) {
8302 simple_type = type->data.klass->enum_basetype->type;
8305 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8308 case MONO_TYPE_STRING: {
8315 str = mono_string_to_utf8 ((MonoString*)arg);
8316 slen = strlen (str);
8317 if ((p-buffer) + 10 + slen >= *buflen) {
8321 newbuf = g_realloc (buffer, *buflen);
8322 p = newbuf + (p-buffer);
8325 mono_metadata_encode_value (slen, p, &p);
8326 memcpy (p, str, slen);
8331 case MONO_TYPE_CLASS: {
8339 k = mono_object_class (arg);
8340 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8341 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8342 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8345 if (rt && (rtc = mono_object_class (rt)) &&
8346 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8347 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8348 arg = (MonoObject *) rt;
8351 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8354 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8355 slen = strlen (str);
8356 if ((p-buffer) + 10 + slen >= *buflen) {
8360 newbuf = g_realloc (buffer, *buflen);
8361 p = newbuf + (p-buffer);
8364 mono_metadata_encode_value (slen, p, &p);
8365 memcpy (p, str, slen);
8370 case MONO_TYPE_SZARRAY: {
8372 MonoClass *eclass, *arg_eclass;
8375 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8378 len = mono_array_length ((MonoArray*)arg);
8380 *p++ = (len >> 8) & 0xff;
8381 *p++ = (len >> 16) & 0xff;
8382 *p++ = (len >> 24) & 0xff;
8384 *retbuffer = buffer;
8385 eclass = type->data.klass;
8386 arg_eclass = mono_object_class (arg)->element_class;
8389 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8390 eclass = mono_defaults.object_class;
8392 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8393 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8394 int elsize = mono_class_array_element_size (arg_eclass);
8395 for (i = 0; i < len; ++i) {
8396 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8399 } else if (eclass->valuetype && arg_eclass->valuetype) {
8400 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8401 int elsize = mono_class_array_element_size (eclass);
8402 for (i = 0; i < len; ++i) {
8403 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8407 for (i = 0; i < len; ++i) {
8408 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8413 case MONO_TYPE_OBJECT: {
8419 * The parameter type is 'object' but the type of the actual
8420 * argument is not. So we have to add type information to the blob
8421 * too. This is completely undocumented in the spec.
8425 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8430 klass = mono_object_class (arg);
8432 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8435 } else if (klass->enumtype) {
8437 } else if (klass == mono_defaults.string_class) {
8438 simple_type = MONO_TYPE_STRING;
8441 } else if (klass->rank == 1) {
8443 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8444 /* See Partition II, Appendix B3 */
8447 *p++ = klass->element_class->byval_arg.type;
8448 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8450 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8451 *p++ = simple_type = klass->byval_arg.type;
8454 g_error ("unhandled type in custom attr");
8456 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8457 slen = strlen (str);
8458 if ((p-buffer) + 10 + slen >= *buflen) {
8462 newbuf = g_realloc (buffer, *buflen);
8463 p = newbuf + (p-buffer);
8466 mono_metadata_encode_value (slen, p, &p);
8467 memcpy (p, str, slen);
8470 simple_type = klass->enum_basetype->type;
8474 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8477 *retbuffer = buffer;
8481 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8483 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8484 char *str = type_get_qualified_name (type, NULL);
8485 int slen = strlen (str);
8489 * This seems to be optional...
8492 mono_metadata_encode_value (slen, p, &p);
8493 memcpy (p, str, slen);
8496 } else if (type->type == MONO_TYPE_OBJECT) {
8498 } else if (type->type == MONO_TYPE_CLASS) {
8499 /* it should be a type: encode_cattr_value () has the check */
8502 mono_metadata_encode_value (type->type, p, &p);
8503 if (type->type == MONO_TYPE_SZARRAY)
8504 /* See the examples in Partition VI, Annex B */
8505 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8512 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8515 /* Preallocate a large enough buffer */
8516 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8517 char *str = type_get_qualified_name (type, NULL);
8520 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8521 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8527 len += strlen (name);
8529 if ((p-buffer) + 20 + len >= *buflen) {
8533 newbuf = g_realloc (buffer, *buflen);
8534 p = newbuf + (p-buffer);
8538 encode_field_or_prop_type (type, p, &p);
8540 len = strlen (name);
8541 mono_metadata_encode_value (len, p, &p);
8542 memcpy (p, name, len);
8544 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8546 *retbuffer = buffer;
8550 * mono_reflection_get_custom_attrs_blob:
8551 * @ctor: custom attribute constructor
8552 * @ctorArgs: arguments o the constructor
8558 * Creates the blob of data that needs to be saved in the metadata and that represents
8559 * the custom attributed described by @ctor, @ctorArgs etc.
8560 * Returns: a Byte array representing the blob of data.
8563 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8566 MonoMethodSignature *sig;
8571 MONO_ARCH_SAVE_REGS;
8573 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8574 /* sig is freed later so allocate it in the heap */
8575 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8577 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8580 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8582 p = buffer = g_malloc (buflen);
8583 /* write the prolog */
8586 for (i = 0; i < sig->param_count; ++i) {
8587 arg = mono_array_get (ctorArgs, MonoObject*, i);
8588 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8592 i += mono_array_length (properties);
8594 i += mono_array_length (fields);
8596 *p++ = (i >> 8) & 0xff;
8599 for (i = 0; i < mono_array_length (properties); ++i) {
8603 prop = mono_array_get (properties, gpointer, i);
8604 get_prop_name_and_type (prop, &pname, &ptype);
8605 *p++ = 0x54; /* PROPERTY signature */
8606 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8613 for (i = 0; i < mono_array_length (fields); ++i) {
8617 field = mono_array_get (fields, gpointer, i);
8618 get_field_name_and_type (field, &fname, &ftype);
8619 *p++ = 0x53; /* FIELD signature */
8620 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8625 g_assert (p - buffer <= buflen);
8626 buflen = p - buffer;
8627 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8628 p = mono_array_addr (result, char, 0);
8629 memcpy (p, buffer, buflen);
8631 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8637 static void* reflection_info_desc = NULL;
8638 #define MOVING_GC_REGISTER(addr) do { \
8639 if (!reflection_info_desc) { \
8641 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8643 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8646 #define MOVING_GC_REGISTER(addr)
8650 * mono_reflection_setup_internal_class:
8651 * @tb: a TypeBuilder object
8653 * Creates a MonoClass that represents the TypeBuilder.
8654 * This is a trick that lets us simplify a lot of reflection code
8655 * (and will allow us to support Build and Run assemblies easier).
8658 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8660 MonoClass *klass, *parent;
8662 MONO_ARCH_SAVE_REGS;
8664 mono_loader_lock ();
8667 /* check so we can compile corlib correctly */
8668 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8669 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8670 parent = tb->parent->type->data.klass;
8672 parent = my_mono_class_from_mono_type (tb->parent->type);
8678 /* the type has already being created: it means we just have to change the parent */
8679 if (tb->type.type) {
8680 klass = mono_class_from_mono_type (tb->type.type);
8681 klass->parent = NULL;
8682 /* fool mono_class_setup_parent */
8683 klass->supertypes = NULL;
8684 mono_class_setup_parent (klass, parent);
8685 mono_class_setup_mono_type (klass);
8686 mono_loader_unlock ();
8690 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8692 klass->image = &tb->module->dynamic_image->image;
8694 klass->inited = 1; /* we lie to the runtime */
8695 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8696 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8697 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8698 klass->flags = tb->attrs;
8700 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8702 klass->element_class = klass;
8704 MOVING_GC_REGISTER (&klass->reflection_info);
8705 klass->reflection_info = tb;
8707 /* Put into cache so mono_class_get () will find it */
8708 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8710 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8711 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8713 if (parent != NULL) {
8714 mono_class_setup_parent (klass, parent);
8715 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8716 const char *old_n = klass->name;
8717 /* trick to get relative numbering right when compiling corlib */
8718 klass->name = "BuildingObject";
8719 mono_class_setup_parent (klass, mono_defaults.object_class);
8720 klass->name = old_n;
8723 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8724 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8725 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8726 klass->instance_size = sizeof (MonoObject);
8727 klass->size_inited = 1;
8728 mono_class_setup_vtable_general (klass, NULL, 0);
8731 mono_class_setup_mono_type (klass);
8733 mono_class_setup_supertypes (klass);
8736 * FIXME: handle interfaces.
8739 tb->type.type = &klass->byval_arg;
8741 if (tb->nesting_type) {
8742 g_assert (tb->nesting_type->type);
8743 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8746 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8748 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8750 mono_loader_unlock ();
8754 * mono_reflection_setup_generic_class:
8755 * @tb: a TypeBuilder object
8757 * Setup the generic class before adding the first generic parameter.
8760 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8764 MONO_ARCH_SAVE_REGS;
8766 klass = my_mono_class_from_mono_type (tb->type.type);
8767 if (tb->generic_container)
8770 tb->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
8771 tb->generic_container->owner.klass = klass;
8775 * mono_reflection_create_generic_class:
8776 * @tb: a TypeBuilder object
8778 * Creates the generic class after all generic parameters have been added.
8781 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8786 MONO_ARCH_SAVE_REGS;
8788 klass = my_mono_class_from_mono_type (tb->type.type);
8790 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8792 if (klass->generic_container || (count == 0))
8795 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8797 klass->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
8799 klass->generic_container->owner.klass = klass;
8800 klass->generic_container->type_argc = count;
8801 klass->generic_container->type_params = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericParam) * count);
8803 for (i = 0; i < count; i++) {
8804 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8805 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8806 /*Make sure we are a diferent type instance */
8807 klass->generic_container->type_params [i].owner = klass->generic_container;
8808 klass->generic_container->type_params [i].pklass = NULL;
8810 g_assert (klass->generic_container->type_params [i].owner);
8813 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8817 * mono_reflection_create_internal_class:
8818 * @tb: a TypeBuilder object
8820 * Actually create the MonoClass that is associated with the TypeBuilder.
8823 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8827 MONO_ARCH_SAVE_REGS;
8829 klass = my_mono_class_from_mono_type (tb->type.type);
8831 mono_loader_lock ();
8832 if (klass->enumtype && klass->enum_basetype == NULL) {
8833 MonoReflectionFieldBuilder *fb;
8836 g_assert (tb->fields != NULL);
8837 g_assert (mono_array_length (tb->fields) >= 1);
8839 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8841 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8842 mono_loader_unlock ();
8846 klass->enum_basetype = fb->type->type;
8847 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8848 if (!klass->element_class)
8849 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8852 * get the element_class from the current corlib.
8854 ec = default_class_from_mono_type (klass->enum_basetype);
8855 klass->instance_size = ec->instance_size;
8856 klass->size_inited = 1;
8858 * this is almost safe to do with enums and it's needed to be able
8859 * to create objects of the enum type (for use in SetConstant).
8861 /* FIXME: Does this mean enums can't have method overrides ? */
8862 mono_class_setup_vtable_general (klass, NULL, 0);
8864 mono_loader_unlock ();
8867 static MonoMarshalSpec*
8868 mono_marshal_spec_from_builder (MonoMemPool *mp, MonoAssembly *assembly,
8869 MonoReflectionMarshal *minfo)
8871 MonoMarshalSpec *res;
8873 res = mp_g_new0 (mp, MonoMarshalSpec, 1);
8874 res->native = minfo->type;
8876 switch (minfo->type) {
8877 case MONO_NATIVE_LPARRAY:
8878 res->data.array_data.elem_type = minfo->eltype;
8879 if (minfo->has_size) {
8880 res->data.array_data.param_num = minfo->param_num;
8881 res->data.array_data.num_elem = minfo->count;
8882 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8885 res->data.array_data.param_num = -1;
8886 res->data.array_data.num_elem = -1;
8887 res->data.array_data.elem_mult = -1;
8891 case MONO_NATIVE_BYVALTSTR:
8892 case MONO_NATIVE_BYVALARRAY:
8893 res->data.array_data.num_elem = minfo->count;
8896 case MONO_NATIVE_CUSTOM:
8897 if (minfo->marshaltyperef)
8898 res->data.custom_data.custom_name =
8899 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8901 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8911 MonoReflectionMarshal*
8912 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8913 MonoMarshalSpec *spec)
8915 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8916 MonoReflectionMarshal *minfo;
8919 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8920 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8921 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8922 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8925 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8926 minfo->type = spec->native;
8928 switch (minfo->type) {
8929 case MONO_NATIVE_LPARRAY:
8930 minfo->eltype = spec->data.array_data.elem_type;
8931 minfo->count = spec->data.array_data.num_elem;
8932 minfo->param_num = spec->data.array_data.param_num;
8935 case MONO_NATIVE_BYVALTSTR:
8936 case MONO_NATIVE_BYVALARRAY:
8937 minfo->count = spec->data.array_data.num_elem;
8940 case MONO_NATIVE_CUSTOM:
8941 if (spec->data.custom_data.custom_name) {
8942 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8944 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8946 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8948 if (spec->data.custom_data.cookie)
8949 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8960 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8961 ReflectionMethodBuilder *rmb,
8962 MonoMethodSignature *sig)
8965 MonoMethodNormal *pm;
8966 MonoMarshalSpec **specs;
8967 MonoReflectionMethodAux *method_aux;
8973 * Methods created using a MethodBuilder should have their memory allocated
8974 * inside the image mempool, while dynamic methods should have their memory
8977 dynamic = rmb->refs != NULL;
8978 mp = dynamic ? NULL : klass->image->mempool;
8981 g_assert (!klass->generic_class);
8983 mono_loader_lock ();
8985 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8986 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8987 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8989 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8991 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8993 pm = (MonoMethodNormal*)m;
8995 m->dynamic = dynamic;
8997 m->flags = rmb->attrs;
8998 m->iflags = rmb->iattrs;
8999 m->name = mp_string_to_utf8 (mp, rmb->name);
9002 m->skip_visibility = rmb->skip_visibility;
9004 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9006 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9007 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9010 m->signature->pinvoke = 1;
9011 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9012 m->signature->pinvoke = 1;
9014 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9016 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
9017 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
9019 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9021 if (klass->image->dynamic)
9022 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9024 mono_loader_unlock ();
9027 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9028 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9029 MonoMethodHeader *header;
9031 gint32 max_stack, i;
9032 gint32 num_locals = 0;
9033 gint32 num_clauses = 0;
9037 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9038 code_size = rmb->ilgen->code_len;
9039 max_stack = rmb->ilgen->max_stack;
9040 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9041 if (rmb->ilgen->ex_handlers)
9042 num_clauses = method_count_clauses (rmb->ilgen);
9045 code = mono_array_addr (rmb->code, guint8, 0);
9046 code_size = mono_array_length (rmb->code);
9047 /* we probably need to run a verifier on the code... */
9057 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
9058 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9059 header->code_size = code_size;
9060 header->code = mp_g_malloc (mp, code_size);
9061 memcpy ((char*)header->code, code, code_size);
9062 header->max_stack = max_stack;
9063 header->init_locals = rmb->init_locals;
9064 header->num_locals = num_locals;
9066 for (i = 0; i < num_locals; ++i) {
9067 MonoReflectionLocalBuilder *lb =
9068 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9070 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
9071 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9074 header->num_clauses = num_clauses;
9076 header->clauses = method_encode_clauses (mp, (MonoDynamicImage*)klass->image,
9077 rmb->ilgen, num_clauses);
9080 pm->header = header;
9083 if (rmb->generic_params) {
9084 int count = mono_array_length (rmb->generic_params);
9085 MonoGenericContainer *container;
9087 container = rmb->generic_container;
9089 m->is_generic = TRUE;
9090 mono_method_set_generic_container (m, container);
9092 container->type_argc = count;
9093 container->type_params = mp_g_new0 (mp, MonoGenericParam, count);
9094 container->owner.method = m;
9096 for (i = 0; i < count; i++) {
9097 MonoReflectionGenericParam *gp =
9098 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9100 container->type_params [i] = *gp->type.type->data.generic_param;
9103 if (klass->generic_container) {
9104 container->parent = klass->generic_container;
9105 container->context.class_inst = klass->generic_container->context.class_inst;
9107 container->context.method_inst = mono_get_shared_generic_inst (container);
9111 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9115 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9117 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
9118 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9119 for (i = 0; i < rmb->nrefs; ++i)
9120 data [i + 1] = rmb->refs [i];
9125 /* Parameter info */
9128 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9129 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
9130 for (i = 0; i <= m->signature->param_count; ++i) {
9131 MonoReflectionParamBuilder *pb;
9132 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9133 if ((i > 0) && (pb->attrs)) {
9134 /* Make a copy since it might point to a shared type structure */
9135 m->signature->params [i - 1] = mono_metadata_type_dup (mp, m->signature->params [i - 1]);
9136 m->signature->params [i - 1]->attrs = pb->attrs;
9139 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9140 MonoDynamicImage *assembly;
9141 guint32 idx, def_type, len;
9145 if (!method_aux->param_defaults) {
9146 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
9147 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
9149 assembly = (MonoDynamicImage*)klass->image;
9150 idx = encode_constant (assembly, pb->def_value, &def_type);
9151 /* Copy the data from the blob since it might get realloc-ed */
9152 p = assembly->blob.data + idx;
9153 len = mono_metadata_decode_blob_size (p, &p2);
9155 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
9156 method_aux->param_default_types [i] = def_type;
9157 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9161 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
9163 if (!method_aux->param_cattr)
9164 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
9165 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (mp, klass->image, pb->cattrs);
9171 /* Parameter marshalling */
9174 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9175 MonoReflectionParamBuilder *pb;
9176 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9177 if (pb->marshal_info) {
9179 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
9180 specs [pb->position] =
9181 mono_marshal_spec_from_builder (mp, klass->image->assembly, pb->marshal_info);
9185 if (specs != NULL) {
9187 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9188 method_aux->param_marshall = specs;
9191 if (klass->image->dynamic && method_aux)
9192 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9194 mono_loader_unlock ();
9200 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9202 ReflectionMethodBuilder rmb;
9203 MonoMethodSignature *sig;
9205 mono_loader_lock ();
9206 sig = ctor_builder_to_signature (klass->image->mempool, mb);
9207 mono_loader_unlock ();
9209 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9211 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9212 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9214 /* If we are in a generic class, we might be called multiple times from inflate_method */
9215 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9216 /* ilgen is no longer needed */
9224 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9226 ReflectionMethodBuilder rmb;
9227 MonoMethodSignature *sig;
9229 mono_loader_lock ();
9230 sig = method_builder_to_signature (klass->image->mempool, mb);
9231 mono_loader_unlock ();
9233 reflection_methodbuilder_from_method_builder (&rmb, mb);
9235 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9236 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9238 /* If we are in a generic class, we might be called multiple times from inflate_method */
9239 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9240 /* ilgen is no longer needed */
9246 static MonoClassField*
9247 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9249 MonoClassField *field;
9253 field = g_new0 (MonoClassField, 1);
9255 field->name = mono_string_to_utf8 (fb->name);
9257 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9258 field->type->attrs = fb->attrs;
9260 field->type = fb->type->type;
9262 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9263 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
9264 if (fb->offset != -1)
9265 field->offset = fb->offset;
9266 field->parent = klass;
9267 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9269 if (fb->def_value) {
9270 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9271 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9272 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9273 /* Copy the data from the blob since it might get realloc-ed */
9274 p = assembly->blob.data + idx;
9275 len = mono_metadata_decode_blob_size (p, &p2);
9277 field->data = g_malloc (len);
9278 memcpy ((gpointer)field->data, p, len);
9285 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9288 MonoReflectionTypeBuilder *tb = NULL;
9289 gboolean is_dynamic = FALSE;
9293 mono_loader_lock ();
9295 domain = mono_object_domain (type);
9297 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9298 tb = (MonoReflectionTypeBuilder *) type;
9301 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9302 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9304 tb = rgi->generic_type;
9308 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9309 if (tb && tb->generic_container)
9310 mono_reflection_create_generic_class (tb);
9312 klass = mono_class_from_mono_type (type->type);
9313 if (!klass->generic_container) {
9314 mono_loader_unlock ();
9318 if (klass->wastypebuilder) {
9319 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9324 mono_loader_unlock ();
9326 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9328 return &geninst->byval_arg;
9332 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9334 MonoGenericClass *gclass;
9335 MonoGenericInst *inst;
9337 g_assert (klass->generic_container);
9339 inst = mono_metadata_get_generic_inst (type_argc, types);
9340 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9342 return mono_generic_class_get_class (gclass);
9345 MonoReflectionMethod*
9346 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9349 MonoMethod *method, *inflated;
9350 MonoMethodInflated *imethod;
9351 MonoReflectionMethodBuilder *mb = NULL;
9352 MonoGenericContext tmp_context;
9353 MonoGenericInst *ginst;
9354 MonoType **type_argv;
9357 MONO_ARCH_SAVE_REGS;
9358 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9359 MonoReflectionTypeBuilder *tb;
9362 mb = (MonoReflectionMethodBuilder *) rmethod;
9363 tb = (MonoReflectionTypeBuilder *) mb->type;
9364 klass = mono_class_from_mono_type (tb->type.type);
9366 method = methodbuilder_to_mono_method (klass, mb);
9368 method = rmethod->method;
9371 klass = method->klass;
9373 if (method->is_inflated)
9374 method = ((MonoMethodInflated *) method)->declaring;
9376 count = mono_method_signature (method)->generic_param_count;
9377 if (count != mono_array_length (types))
9380 type_argv = g_new0 (MonoType *, count);
9381 for (i = 0; i < count; i++) {
9382 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9383 type_argv [i] = garg->type;
9385 ginst = mono_metadata_get_generic_inst (count, type_argv);
9388 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9389 tmp_context.method_inst = ginst;
9391 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9392 imethod = (MonoMethodInflated *) inflated;
9394 if (method->klass->image->dynamic) {
9395 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9397 * This table maps metadata structures representing inflated methods/fields
9398 * to the reflection objects representing their generic definitions.
9400 mono_loader_lock ();
9401 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9402 mono_loader_unlock ();
9405 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9409 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9411 MonoMethodInflated *imethod;
9412 MonoGenericContext *context;
9415 g_assert (klass->generic_class);
9416 context = mono_class_get_context (klass);
9418 if (klass->method.count) {
9419 /* Find the already created inflated method */
9420 for (i = 0; i < klass->method.count; ++i) {
9421 g_assert (klass->methods [i]->is_inflated);
9422 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9425 g_assert (i < klass->method.count);
9426 imethod = (MonoMethodInflated*)klass->methods [i];
9428 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9431 if (method->is_generic && method->klass->image->dynamic) {
9432 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9434 mono_loader_lock ();
9435 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9436 mono_loader_unlock ();
9438 return (MonoMethod *) imethod;
9442 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9447 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9449 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9450 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9451 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9453 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9454 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9455 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9456 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9457 method = ((MonoReflectionMethod *) obj)->method;
9459 method = NULL; /* prevent compiler warning */
9460 g_assert_not_reached ();
9463 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9466 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9468 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9469 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9472 MonoGenericClass *gclass;
9473 MonoDynamicGenericClass *dgclass;
9474 MonoClass *klass, *gklass;
9477 MONO_ARCH_SAVE_REGS;
9479 klass = mono_class_from_mono_type (type->type.type);
9480 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9481 gclass = type->type.type->data.generic_class;
9483 g_assert (gclass->is_dynamic);
9484 dgclass = (MonoDynamicGenericClass *) gclass;
9486 if (dgclass->initialized)
9489 gklass = gclass->container_class;
9490 mono_class_init (gklass);
9492 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9493 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9494 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9495 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9496 dgclass->count_events = events ? mono_array_length (events) : 0;
9498 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9499 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9500 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9501 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9502 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9504 for (i = 0; i < dgclass->count_methods; i++) {
9505 MonoObject *obj = mono_array_get (methods, gpointer, i);
9507 dgclass->methods [i] = inflate_method (type, obj);
9510 for (i = 0; i < dgclass->count_ctors; i++) {
9511 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9513 dgclass->ctors [i] = inflate_method (type, obj);
9516 for (i = 0; i < dgclass->count_fields; i++) {
9517 MonoObject *obj = mono_array_get (fields, gpointer, i);
9518 MonoClassField *field, *inflated_field = NULL;
9519 MonoInflatedField *ifield;
9521 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9522 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9523 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9524 field = ((MonoReflectionField *) obj)->field;
9526 field = NULL; /* prevent compiler warning */
9527 g_assert_not_reached ();
9530 ifield = g_new0 (MonoInflatedField, 1);
9531 ifield->generic_type = field->type;
9532 MOVING_GC_REGISTER (&ifield->reflection_info);
9533 ifield->reflection_info = obj;
9535 dgclass->fields [i] = *field;
9536 dgclass->fields [i].parent = klass;
9537 dgclass->fields [i].generic_info = ifield;
9538 dgclass->fields [i].type = mono_class_inflate_generic_type (
9539 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9541 if (inflated_field) {
9542 g_free ((char*)inflated_field->data);
9543 g_free (inflated_field);
9545 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9549 for (i = 0; i < dgclass->count_properties; i++) {
9550 MonoObject *obj = mono_array_get (properties, gpointer, i);
9551 MonoProperty *property = &dgclass->properties [i];
9553 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9554 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9556 property->parent = klass;
9557 property->attrs = pb->attrs;
9558 property->name = mono_string_to_utf8 (pb->name);
9560 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9562 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9563 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9564 *property = *((MonoReflectionProperty *) obj)->property;
9565 property->name = g_strdup (property->name);
9568 property->get = inflate_mono_method (klass, property->get, NULL);
9570 property->set = inflate_mono_method (klass, property->set, NULL);
9572 g_assert_not_reached ();
9575 for (i = 0; i < dgclass->count_events; i++) {
9576 MonoObject *obj = mono_array_get (events, gpointer, i);
9577 MonoEvent *event = &dgclass->events [i];
9579 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9580 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9582 event->parent = klass;
9583 event->attrs = eb->attrs;
9584 event->name = mono_string_to_utf8 (eb->name);
9586 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9587 if (eb->remove_method)
9588 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9589 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9590 *event = *((MonoReflectionEvent *) obj)->event;
9591 event->name = g_strdup (event->name);
9594 event->add = inflate_mono_method (klass, event->add, NULL);
9596 event->remove = inflate_mono_method (klass, event->remove, NULL);
9598 g_assert_not_reached ();
9601 dgclass->initialized = TRUE;
9605 ensure_runtime_vtable (MonoClass *klass)
9607 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9610 if (!tb || klass->wastypebuilder)
9613 ensure_runtime_vtable (klass->parent);
9615 num = tb->ctors? mono_array_length (tb->ctors): 0;
9616 num += tb->num_methods;
9617 klass->method.count = num;
9618 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9619 num = tb->ctors? mono_array_length (tb->ctors): 0;
9620 for (i = 0; i < num; ++i)
9621 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9622 num = tb->num_methods;
9624 for (i = 0; i < num; ++i)
9625 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9627 if (tb->interfaces) {
9628 klass->interface_count = mono_array_length (tb->interfaces);
9629 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9630 for (i = 0; i < klass->interface_count; ++i) {
9631 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9632 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9636 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9637 for (i = 0; i < klass->method.count; ++i)
9638 klass->methods [i]->slot = i;
9640 mono_class_setup_interface_offsets (klass);
9644 * The generic vtable is needed even if image->run is not set since some
9645 * runtime code like ves_icall_Type_GetMethodsByName depends on
9646 * method->slot being defined.
9650 * tb->methods could not be freed since it is used for determining
9651 * overrides during dynamic vtable construction.
9656 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9658 MonoReflectionTypeBuilder *tb;
9664 g_assert (klass->image->dynamic);
9666 if (!klass->reflection_info)
9669 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9671 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9675 for (i = 0; i < tb->num_methods; ++i) {
9676 MonoReflectionMethodBuilder *mb =
9677 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9678 if (mb->override_method)
9684 *overrides = g_new0 (MonoMethod*, onum * 2);
9687 for (i = 0; i < tb->num_methods; ++i) {
9688 MonoReflectionMethodBuilder *mb =
9689 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9690 if (mb->override_method) {
9691 (*overrides) [onum * 2] =
9692 mb->override_method->method;
9693 (*overrides) [onum * 2 + 1] =
9696 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9697 g_assert (mb->override_method->method);
9698 g_assert (mb->mhandle);
9705 *num_overrides = onum;
9709 typebuilder_setup_fields (MonoClass *klass)
9711 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9712 MonoReflectionFieldBuilder *fb;
9713 MonoClassField *field;
9714 MonoMemPool *mp = klass->image->mempool;
9719 klass->field.count = tb->num_fields;
9720 klass->field.first = 0;
9722 if (!klass->field.count)
9725 klass->fields = mp_g_new0 (mp, MonoClassField, klass->field.count);
9727 for (i = 0; i < klass->field.count; ++i) {
9728 fb = mono_array_get (tb->fields, gpointer, i);
9729 field = &klass->fields [i];
9730 field->name = mp_string_to_utf8 (mp, fb->name);
9732 field->type = mono_metadata_type_dup (mp, fb->type->type);
9733 field->type->attrs = fb->attrs;
9735 field->type = fb->type->type;
9737 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9738 field->data = mono_array_addr (fb->rva_data, char, 0);
9739 if (fb->offset != -1)
9740 field->offset = fb->offset;
9741 field->parent = klass;
9743 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9745 if (fb->def_value) {
9746 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9747 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9748 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9749 /* Copy the data from the blob since it might get realloc-ed */
9750 p = assembly->blob.data + idx;
9751 len = mono_metadata_decode_blob_size (p, &p2);
9753 field->data = mono_mempool_alloc (mp, len);
9754 memcpy ((gpointer)field->data, p, len);
9757 mono_class_layout_fields (klass);
9761 typebuilder_setup_properties (MonoClass *klass)
9763 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9764 MonoReflectionPropertyBuilder *pb;
9765 MonoMemPool *mp = klass->image->mempool;
9768 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9769 klass->property.first = 0;
9771 klass->properties = mp_g_new0 (mp, MonoProperty, klass->property.count);
9772 for (i = 0; i < klass->property.count; ++i) {
9773 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9774 klass->properties [i].parent = klass;
9775 klass->properties [i].attrs = pb->attrs;
9776 klass->properties [i].name = mp_string_to_utf8 (mp, pb->name);
9778 klass->properties [i].get = pb->get_method->mhandle;
9780 klass->properties [i].set = pb->set_method->mhandle;
9782 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9786 MonoReflectionEvent *
9787 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9789 MonoEvent *event = g_new0 (MonoEvent, 1);
9793 klass = my_mono_class_from_mono_type (tb->type.type);
9795 event->parent = klass;
9796 event->attrs = eb->attrs;
9797 event->name = mono_string_to_utf8 (eb->name);
9799 event->add = eb->add_method->mhandle;
9800 if (eb->remove_method)
9801 event->remove = eb->remove_method->mhandle;
9802 if (eb->raise_method)
9803 event->raise = eb->raise_method->mhandle;
9805 if (eb->other_methods) {
9806 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9807 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9808 MonoReflectionMethodBuilder *mb =
9809 mono_array_get (eb->other_methods,
9810 MonoReflectionMethodBuilder*, j);
9811 event->other [j] = mb->mhandle;
9815 return mono_event_get_object (mono_object_domain (tb), klass, event);
9819 typebuilder_setup_events (MonoClass *klass)
9821 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9822 MonoReflectionEventBuilder *eb;
9823 MonoMemPool *mp = klass->image->mempool;
9826 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9827 klass->event.first = 0;
9829 klass->events = mp_g_new0 (mp, MonoEvent, klass->event.count);
9830 for (i = 0; i < klass->event.count; ++i) {
9831 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9832 klass->events [i].parent = klass;
9833 klass->events [i].attrs = eb->attrs;
9834 klass->events [i].name = mp_string_to_utf8 (mp, eb->name);
9836 klass->events [i].add = eb->add_method->mhandle;
9837 if (eb->remove_method)
9838 klass->events [i].remove = eb->remove_method->mhandle;
9839 if (eb->raise_method)
9840 klass->events [i].raise = eb->raise_method->mhandle;
9842 if (eb->other_methods) {
9843 klass->events [i].other = mp_g_new0 (mp, MonoMethod*, mono_array_length (eb->other_methods) + 1);
9844 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9845 MonoReflectionMethodBuilder *mb =
9846 mono_array_get (eb->other_methods,
9847 MonoReflectionMethodBuilder*, j);
9848 klass->events [i].other [j] = mb->mhandle;
9851 mono_save_custom_attrs (klass->image, &klass->events [i], eb->cattrs);
9856 remove_instantiations_of (gpointer key,
9860 MonoType *type = (MonoType*)key;
9861 MonoClass *klass = (MonoClass*)user_data;
9863 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
9870 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9874 MonoReflectionType* res;
9877 MONO_ARCH_SAVE_REGS;
9879 domain = mono_object_domain (tb);
9880 klass = my_mono_class_from_mono_type (tb->type.type);
9882 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9885 * we need to lock the domain because the lock will be taken inside
9886 * So, we need to keep the locking order correct.
9888 mono_domain_lock (domain);
9889 mono_loader_lock ();
9890 if (klass->wastypebuilder) {
9891 mono_loader_unlock ();
9892 mono_domain_unlock (domain);
9893 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9896 * Fields to set in klass:
9897 * the various flags: delegate/unicode/contextbound etc.
9899 klass->flags = tb->attrs;
9900 klass->has_cctor = 1;
9901 klass->has_finalize = 1;
9904 if (!((MonoDynamicImage*)klass->image)->run) {
9905 if (klass->generic_container) {
9906 /* FIXME: The code below can't handle generic classes */
9907 klass->wastypebuilder = TRUE;
9908 mono_loader_unlock ();
9909 mono_domain_unlock (domain);
9910 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9915 /* enums are done right away */
9916 if (!klass->enumtype)
9917 ensure_runtime_vtable (klass);
9920 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9921 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9922 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9926 /* fields and object layout */
9927 if (klass->parent) {
9928 if (!klass->parent->size_inited)
9929 mono_class_init (klass->parent);
9930 klass->instance_size = klass->parent->instance_size;
9931 klass->sizes.class_size = 0;
9932 klass->min_align = klass->parent->min_align;
9933 /* if the type has no fields we won't call the field_setup
9934 * routine which sets up klass->has_references.
9936 klass->has_references |= klass->parent->has_references;
9938 klass->instance_size = sizeof (MonoObject);
9939 klass->min_align = 1;
9942 /* FIXME: handle packing_size and instance_size */
9943 typebuilder_setup_fields (klass);
9945 typebuilder_setup_properties (klass);
9947 typebuilder_setup_events (klass);
9949 klass->wastypebuilder = TRUE;
9952 * If we are a generic TypeBuilder, there might be instantiations in the type cache
9953 * which have type System.Reflection.MonoGenericClass, but after the type is created,
9954 * we want to return normal System.MonoType objects, so clear these out from the cache.
9956 if (domain->type_hash && klass->generic_container)
9957 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
9959 mono_loader_unlock ();
9960 mono_domain_unlock (domain);
9962 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
9963 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
9964 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
9967 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9968 g_assert (res != (MonoReflectionType*)tb);
9974 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9976 MonoGenericParam *param;
9979 MONO_ARCH_SAVE_REGS;
9981 param = g_new0 (MonoGenericParam, 1);
9983 if (gparam->mbuilder) {
9984 if (!gparam->mbuilder->generic_container) {
9985 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
9986 MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
9987 gparam->mbuilder->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
9988 gparam->mbuilder->generic_container->is_method = TRUE;
9990 param->owner = gparam->mbuilder->generic_container;
9991 } else if (gparam->tbuilder) {
9992 g_assert (gparam->tbuilder->generic_container);
9993 param->owner = gparam->tbuilder->generic_container;
9996 param->name = mono_string_to_utf8 (gparam->name);
9997 param->num = gparam->index;
9999 image = &gparam->tbuilder->module->dynamic_image->image;
10000 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10002 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
10003 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10005 gparam->type.type = g_new0 (MonoType, 1);
10006 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
10007 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
10008 gparam->type.type->data.generic_param = param;
10012 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10014 MonoDynamicImage *assembly = sig->module->dynamic_image;
10015 guint32 na = mono_array_length (sig->arguments);
10020 sigbuffer_init (&buf, 32);
10022 sigbuffer_add_value (&buf, 0x07);
10023 sigbuffer_add_value (&buf, na);
10024 for (i = 0; i < na; ++i) {
10025 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10026 encode_reflection_type (assembly, type, &buf);
10029 buflen = buf.p - buf.buf;
10030 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10031 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10032 sigbuffer_free (&buf);
10038 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10040 MonoDynamicImage *assembly = sig->module->dynamic_image;
10041 guint32 na = mono_array_length (sig->arguments);
10046 sigbuffer_init (&buf, 32);
10048 sigbuffer_add_value (&buf, 0x06);
10049 for (i = 0; i < na; ++i) {
10050 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10051 encode_reflection_type (assembly, type, &buf);
10054 buflen = buf.p - buf.buf;
10055 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10056 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10057 sigbuffer_free (&buf);
10063 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10065 ReflectionMethodBuilder rmb;
10066 MonoMethodSignature *sig;
10071 sig = dynamic_method_to_signature (mb);
10073 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10076 * Resolve references.
10079 * Every second entry in the refs array is reserved for storing handle_class,
10080 * which is needed by the ldtoken implementation in the JIT.
10082 rmb.nrefs = mb->nrefs;
10083 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10084 for (i = 0; i < mb->nrefs; i += 2) {
10085 MonoClass *handle_class;
10087 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10089 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10090 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10092 * The referenced DynamicMethod should already be created by the managed
10093 * code, except in the case of circular references. In that case, we store
10094 * method in the refs array, and fix it up later when the referenced
10095 * DynamicMethod is created.
10097 if (method->mhandle) {
10098 ref = method->mhandle;
10100 /* FIXME: GC object stored in unmanaged memory */
10103 /* FIXME: GC object stored in unmanaged memory */
10104 method->referenced_by = g_slist_append (method->referenced_by, mb);
10106 handle_class = mono_defaults.methodhandle_class;
10108 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10111 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10116 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10117 rmb.refs [i + 1] = handle_class;
10120 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10122 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10124 /* Fix up refs entries pointing at us */
10125 for (l = mb->referenced_by; l; l = l->next) {
10126 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10127 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10130 g_assert (method->mhandle);
10132 data = (gpointer*)wrapper->method_data;
10133 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10134 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10135 data [i + 1] = mb->mhandle;
10138 g_slist_free (mb->referenced_by);
10142 /* ilgen is no longer needed */
10147 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10152 mono_runtime_free_method (
10153 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10158 * mono_reflection_is_valid_dynamic_token:
10160 * Returns TRUE if token is valid.
10164 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10166 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10170 * mono_reflection_lookup_dynamic_token:
10172 * Finish the Builder object pointed to by TOKEN and return the corresponding
10173 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10174 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10178 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10180 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10184 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10187 g_assert_not_reached ();
10193 handle_class = &klass;
10194 return resolve_object (image, obj, handle_class, context);
10198 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10200 gpointer result = NULL;
10202 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10203 result = mono_string_intern ((MonoString*)obj);
10204 *handle_class = NULL;
10206 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10207 MonoReflectionType *tb = (MonoReflectionType*)obj;
10209 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10210 result = mono_class_from_mono_type (inflated);
10211 mono_metadata_free_type (inflated);
10213 result = mono_class_from_mono_type (tb->type);
10215 *handle_class = mono_defaults.typehandle_class;
10217 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10218 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10219 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10220 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10221 result = ((MonoReflectionMethod*)obj)->method;
10223 result = mono_class_inflate_generic_method (result, context);
10224 *handle_class = mono_defaults.methodhandle_class;
10226 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10227 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10228 result = mb->mhandle;
10230 /* Type is not yet created */
10231 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10233 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10236 * Hopefully this has been filled in by calling CreateType() on the
10240 * TODO: This won't work if the application finishes another
10241 * TypeBuilder instance instead of this one.
10243 result = mb->mhandle;
10246 result = mono_class_inflate_generic_method (result, context);
10247 *handle_class = mono_defaults.methodhandle_class;
10248 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10249 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10251 result = cb->mhandle;
10253 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10255 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10256 result = cb->mhandle;
10259 result = mono_class_inflate_generic_method (result, context);
10260 *handle_class = mono_defaults.methodhandle_class;
10261 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10262 result = ((MonoReflectionField*)obj)->field;
10263 *handle_class = mono_defaults.fieldhandle_class;
10265 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10266 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10267 result = fb->handle;
10270 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10272 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10273 result = fb->handle;
10276 if (fb->handle && fb->handle->parent->generic_container) {
10277 MonoClass *klass = fb->handle->parent;
10278 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10279 MonoClass *inflated = mono_class_from_mono_type (type);
10281 result = mono_class_get_field_from_name (inflated, fb->handle->name);
10283 mono_metadata_free_type (type);
10285 *handle_class = mono_defaults.fieldhandle_class;
10286 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10287 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10290 klass = tb->type.type->data.klass;
10291 if (klass->wastypebuilder) {
10292 /* Already created */
10296 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10297 result = tb->type.type->data.klass;
10300 *handle_class = mono_defaults.typehandle_class;
10301 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10302 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10303 MonoMethodSignature *sig;
10306 if (helper->arguments)
10307 nargs = mono_array_length (helper->arguments);
10311 sig = mono_metadata_signature_alloc (image, nargs);
10312 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10313 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10315 if (helper->call_conv == 0) /* unmanaged */
10316 sig->call_convention = helper->unmanaged_call_conv - 1;
10318 if (helper->call_conv & 0x02)
10319 sig->call_convention = MONO_CALL_VARARG;
10321 sig->call_convention = MONO_CALL_DEFAULT;
10323 sig->param_count = nargs;
10324 /* TODO: Copy type ? */
10325 sig->ret = helper->return_type->type;
10326 for (i = 0; i < nargs; ++i) {
10327 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10328 sig->params [i] = rt->type;
10332 *handle_class = NULL;
10333 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10334 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10335 /* Already created by the managed code */
10336 g_assert (method->mhandle);
10337 result = method->mhandle;
10338 *handle_class = mono_defaults.methodhandle_class;
10339 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10340 MonoReflectionType *tb = (MonoReflectionType*)obj;
10341 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10342 result = mono_class_from_mono_type (type);
10343 *handle_class = mono_defaults.typehandle_class;
10345 mono_metadata_free_type (type);
10346 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10347 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10348 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10349 result = mono_class_from_mono_type (type);
10350 *handle_class = mono_defaults.typehandle_class;
10352 mono_metadata_free_type (type);
10353 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10354 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10355 MonoClass *inflated;
10358 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10359 inflated = mono_class_from_mono_type (type);
10361 g_assert (f->fb->handle);
10362 result = mono_class_get_field_from_name (inflated, f->fb->handle->name);
10364 mono_metadata_free_type (type);
10365 *handle_class = mono_defaults.fieldhandle_class;
10366 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10367 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10368 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10369 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10370 g_assert (c->cb->mhandle);
10371 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10372 *handle_class = mono_defaults.methodhandle_class;
10373 mono_metadata_free_type (type);
10374 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10375 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10376 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10377 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10378 g_assert (m->mb->mhandle);
10379 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10380 *handle_class = mono_defaults.methodhandle_class;
10381 mono_metadata_free_type (type);
10383 g_print (obj->vtable->klass->name);
10384 g_assert_not_reached ();
10390 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10391 const static guint32 declsec_flags_map[] = {
10392 0x00000000, /* empty */
10393 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10394 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10395 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10396 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10397 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10398 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10399 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10400 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10401 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10402 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10403 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10404 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10405 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10406 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10407 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10408 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10409 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10410 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10414 * Returns flags that includes all available security action associated to the handle.
10415 * @token: metadata token (either for a class or a method)
10416 * @image: image where resides the metadata.
10419 mono_declsec_get_flags (MonoImage *image, guint32 token)
10421 int index = mono_metadata_declsec_from_index (image, token);
10422 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10423 guint32 result = 0;
10427 /* HasSecurity can be present for other, not specially encoded, attributes,
10428 e.g. SuppressUnmanagedCodeSecurityAttribute */
10432 for (i = index; i < t->rows; i++) {
10433 guint32 cols [MONO_DECL_SECURITY_SIZE];
10435 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10436 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10439 action = cols [MONO_DECL_SECURITY_ACTION];
10440 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10441 result |= declsec_flags_map [action];
10443 g_assert_not_reached ();
10450 * Get the security actions (in the form of flags) associated with the specified method.
10452 * @method: The method for which we want the declarative security flags.
10453 * Return the declarative security flags for the method (only).
10455 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10456 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10459 mono_declsec_flags_from_method (MonoMethod *method)
10461 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10462 /* FIXME: No cache (for the moment) */
10463 guint32 idx = mono_method_get_index (method);
10464 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10465 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10466 return mono_declsec_get_flags (method->klass->image, idx);
10472 * Get the security actions (in the form of flags) associated with the specified class.
10474 * @klass: The class for which we want the declarative security flags.
10475 * Return the declarative security flags for the class.
10477 * Note: We cache the flags inside the MonoClass structure as this will get
10478 * called very often (at least for each method).
10481 mono_declsec_flags_from_class (MonoClass *klass)
10483 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10484 if (!klass->declsec_flags) {
10485 guint32 idx = mono_metadata_token_index (klass->type_token);
10486 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10487 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10488 /* we cache the flags on classes */
10489 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10491 return klass->declsec_flags;
10497 * Get the security actions (in the form of flags) associated with the specified assembly.
10499 * @assembly: The assembly for which we want the declarative security flags.
10500 * Return the declarative security flags for the assembly.
10503 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10505 guint32 idx = 1; /* there is only one assembly */
10506 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10507 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10508 return mono_declsec_get_flags (assembly->image, idx);
10513 * Fill actions for the specific index (which may either be an encoded class token or
10514 * an encoded method token) from the metadata image.
10515 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10518 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10519 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10521 MonoBoolean result = FALSE;
10523 guint32 cols [MONO_DECL_SECURITY_SIZE];
10524 int index = mono_metadata_declsec_from_index (image, token);
10527 t = &image->tables [MONO_TABLE_DECLSECURITY];
10528 for (i = index; i < t->rows; i++) {
10529 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10531 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10534 /* if present only replace (class) permissions with method permissions */
10535 /* if empty accept either class or method permissions */
10536 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10537 if (!actions->demand.blob) {
10538 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10539 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10540 actions->demand.blob = (char*) (blob + 2);
10541 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10544 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10545 if (!actions->noncasdemand.blob) {
10546 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10547 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10548 actions->noncasdemand.blob = (char*) (blob + 2);
10549 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10552 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10553 if (!actions->demandchoice.blob) {
10554 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10555 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10556 actions->demandchoice.blob = (char*) (blob + 2);
10557 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10567 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
10568 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10570 guint32 idx = mono_metadata_token_index (klass->type_token);
10571 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10572 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10573 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
10577 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
10578 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10580 guint32 idx = mono_method_get_index (method);
10581 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10582 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10583 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10587 * Collect all actions (that requires to generate code in mini) assigned for
10588 * the specified method.
10589 * Note: Don't use the content of actions if the function return FALSE.
10592 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10594 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
10595 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10596 MonoBoolean result = FALSE;
10599 /* quick exit if no declarative security is present in the metadata */
10600 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10603 /* we want the original as the wrapper is "free" of the security informations */
10604 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10605 method = mono_marshal_method_from_wrapper (method);
10610 /* First we look for method-level attributes */
10611 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10612 mono_class_init (method->klass);
10613 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10615 result = mono_declsec_get_method_demands_params (method, demands,
10616 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10619 /* Here we use (or create) the class declarative cache to look for demands */
10620 flags = mono_declsec_flags_from_class (method->klass);
10621 if (flags & mask) {
10623 mono_class_init (method->klass);
10624 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10626 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10627 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10630 /* The boolean return value is used as a shortcut in case nothing needs to
10631 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10637 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10639 * Note: Don't use the content of actions if the function return FALSE.
10642 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10644 MonoBoolean result = FALSE;
10647 /* quick exit if no declarative security is present in the metadata */
10648 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10651 /* we want the original as the wrapper is "free" of the security informations */
10652 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10653 method = mono_marshal_method_from_wrapper (method);
10658 /* results are independant - zeroize both */
10659 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10660 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10662 /* First we look for method-level attributes */
10663 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10664 mono_class_init (method->klass);
10666 result = mono_declsec_get_method_demands_params (method, cmethod,
10667 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10670 /* Here we use (or create) the class declarative cache to look for demands */
10671 flags = mono_declsec_flags_from_class (method->klass);
10672 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10673 mono_class_init (method->klass);
10675 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10676 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10683 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10685 * @klass The inherited class - this is the class that provides the security check (attributes)
10687 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10689 * Note: Don't use the content of actions if the function return FALSE.
10692 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10694 MonoBoolean result = FALSE;
10697 /* quick exit if no declarative security is present in the metadata */
10698 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10701 /* Here we use (or create) the class declarative cache to look for demands */
10702 flags = mono_declsec_flags_from_class (klass);
10703 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10704 mono_class_init (klass);
10705 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10707 result |= mono_declsec_get_class_demands_params (klass, demands,
10708 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10715 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10717 * Note: Don't use the content of actions if the function return FALSE.
10720 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10722 /* quick exit if no declarative security is present in the metadata */
10723 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10726 /* we want the original as the wrapper is "free" of the security informations */
10727 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10728 method = mono_marshal_method_from_wrapper (method);
10733 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10734 mono_class_init (method->klass);
10735 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10737 return mono_declsec_get_method_demands_params (method, demands,
10738 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10745 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10747 guint32 cols [MONO_DECL_SECURITY_SIZE];
10751 int index = mono_metadata_declsec_from_index (image, token);
10755 t = &image->tables [MONO_TABLE_DECLSECURITY];
10756 for (i = index; i < t->rows; i++) {
10757 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10759 /* shortcut - index are ordered */
10760 if (token != cols [MONO_DECL_SECURITY_PARENT])
10763 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10764 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10765 entry->blob = (char*) (metadata + 2);
10766 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10775 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10777 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10778 guint32 idx = mono_method_get_index (method);
10779 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10780 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10781 return get_declsec_action (method->klass->image, idx, action, entry);
10787 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10790 guint32 flags = mono_declsec_flags_from_class (klass);
10791 if (declsec_flags_map [action] & flags) {
10792 guint32 idx = mono_metadata_token_index (klass->type_token);
10793 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10794 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10795 return get_declsec_action (klass->image, idx, action, entry);
10801 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10803 guint32 idx = 1; /* there is only one assembly */
10804 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10805 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10807 return get_declsec_action (assembly->image, idx, action, entry);
10811 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10813 MonoObject *res, *exc;
10815 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10816 static MonoMethod *method = NULL;
10818 if (!System_Reflection_Emit_TypeBuilder) {
10819 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10820 g_assert (System_Reflection_Emit_TypeBuilder);
10822 if (method == NULL) {
10823 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10828 * The result of mono_type_get_object () might be a System.MonoType but we
10829 * need a TypeBuilder so use klass->reflection_info.
10831 g_assert (klass->reflection_info);
10832 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10834 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10836 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10840 return *(MonoBoolean*)mono_object_unbox (res);